1 -- this file provides project_add_extern_libs, which takes care of the
2 -- dirty details of adding the libraries' include and lib paths.
4 -- TYPICAL TASK: add new library. Instructions:
5 -- 1) add a new extern_lib_defs entry
6 -- 2) add library name to extern_libs tables in premake.lua for all 'projects' that want to use it
8 -- directory in which OS-specific library subdirectories reside.
9 if os
.istarget("macosx") then
10 libraries_dir
= rootdir
.."/libraries/osx/"
11 elseif os
.istarget("windows") then
12 libraries_dir
= rootdir
.."/libraries/win32/"
14 -- No Unix-specific libs yet (use source directory instead!)
16 -- directory for shared, bundled libraries
17 libraries_source_dir
= rootdir
.."/libraries/source/"
18 third_party_source_dir
= rootdir
.."/source/third_party/"
20 local function add_default_lib_paths(extern_lib
)
21 libdirs
{ libraries_dir
.. extern_lib
.. "/lib" }
24 local function add_source_lib_paths(extern_lib
)
25 libdirs
{ libraries_source_dir
.. extern_lib
.. "/lib" }
28 local function add_default_include_paths(extern_lib
)
29 sysincludedirs
{ libraries_dir
.. extern_lib
.. "/include" }
32 local function add_source_include_paths(extern_lib
)
33 sysincludedirs
{ libraries_source_dir
.. extern_lib
.. "/include" }
36 local function add_third_party_include_paths(extern_lib
)
37 sysincludedirs
{ third_party_source_dir
.. extern_lib
.. "/include" }
40 pkgconfig
= require
"pkgconfig"
42 -- Configure pkgconfig for MacOSX systems
43 if os
.istarget("macosx") then
44 pkgconfig
.additional_pc_path
= libraries_dir
.. "pkgconfig/"
45 pkgconfig
.static_link_libs
= true
48 local function add_delayload(name
, suffix
, def
)
50 if def
["no_delayload"] then
54 -- currently only supported by VC; nothing to do on other platforms.
55 if not os
.istarget("windows") then
59 -- no extra debug version; use same library in all configs
61 linkoptions
{ "/DELAYLOAD:"..name
..".dll" }
62 -- extra debug version available; use in debug config
64 local dbg_cmd
= "/DELAYLOAD:" .. name
.. suffix
.. ".dll"
65 local cmd
= "/DELAYLOAD:" .. name
.. ".dll"
68 linkoptions
{ dbg_cmd
}
76 local function add_default_links(def
)
78 -- careful: make sure to only use *_names when on the correct platform.
80 if os
.istarget("windows") then
84 elseif _OPTIONS
["android"] and def
.android_names
then
85 names
= def
.android_names
86 elseif os
.istarget("linux") and def
.linux_names
then
87 names
= def
.linux_names
88 elseif os
.istarget("macosx") and (def
.osx_names
or def
.osx_frameworks
) then
92 -- OS X "Frameworks" are added to the links as "name.framework"
93 if def
.osx_frameworks
then
94 for i
,name
in pairs(def
.osx_frameworks
) do
95 links
{ name
.. ".framework" }
98 elseif os
.istarget("bsd") and def
.bsd_names
then
100 elseif def
.unix_names
then
101 names
= def
.unix_names
105 -- library is overriding default suffix (typically "" to indicate there is none)
106 if def
["dbg_suffix"] then
107 suffix
= def
["dbg_suffix"]
109 -- non-Windows doesn't have the distinction of debug vs. release libraries
110 -- (to be more specific, they do, but the two are binary compatible;
111 -- usually only one type - debug or release - is installed at a time).
112 if not os
.istarget("windows") then
116 for i
,name
in pairs(names
) do
118 links
{ name
.. suffix
}
123 add_delayload(name
, suffix
, def
)
128 -- Library definitions
129 -- In a perfect world, libraries would have a common installation template,
130 -- i.e. location of include directory, naming convention for .lib, etc.
131 -- this table provides a means of working around each library's differences.
133 -- The basic approach is defining two functions per library:
135 -- 1. compile_settings
136 -- This function should set all settings requred during the compile-phase like
137 -- includedirs, defines etc...
140 -- This function should set all settings required during the link-phase like
141 -- libdirs, linkflag etc...
143 -- The main reason for separating those settings is different linking behaviour
144 -- on osx and xcode. For more details, read the comment in project_add_extern_libs.
146 -- There are some helper functions for the most common tasks. You should use them
147 -- if they can be used in your situation to make the definitions more consistent and
148 -- use their default beviours as a guideline.
151 -- add_default_lib_paths(extern_lib)
152 -- Description: Add '<libraries root>/<libraryname>/lib'to the libpaths
154 -- * extern_lib: <libraryname> to be used in the libpath.
156 -- add_default_include_paths(extern_lib)
157 -- Description: Add '<libraries root>/<libraryname>/include' to the includepaths
159 -- * extern_lib: <libraryname> to be used in the libpath.
162 -- Description: Adds links to libraries and configures delayloading.
163 -- If the *_names parameter for a plattform is missing, no linking will be done
164 -- on that plattform.
165 -- The default assumptions are:
166 -- * debug import library and DLL are distinguished with a "d" suffix
167 -- * the library should be marked for delay-loading.
169 -- * win_names: table of import library / DLL names (no extension) when
170 -- running on Windows.
171 -- * unix_names: as above; shared object names when running on non-Windows.
172 -- * osx_names, osx_frameworks: for OS X specifically; if any of those is
173 -- specified, unix_names is ignored. Using both is possible if needed.
174 -- * osx_names: as above.
175 -- * osx_frameworks: as above, for system libraries that need to be linked
176 -- as "name.framework".
177 -- * bsd_names: as above; for BSD specifically (overrides unix_names if both are
179 -- * linux_names: ditto for Linux (overrides unix_names if both given)
180 -- * dbg_suffix: changes the debug suffix from the above default.
181 -- can be "" to indicate the library doesn't have a debug build;
182 -- in that case, the same library (without suffix) is used in
183 -- all build configurations.
184 -- * no_delayload: indicate the library is not to be delay-loaded.
185 -- this is necessary for some libraries that do not support it,
186 -- e.g. Xerces (which is so stupid as to export variables).
190 compile_settings
= function()
191 if os
.istarget("windows") then
192 -- Force the autolink to use the vc141 libs.
193 defines
{ 'BOOST_LIB_TOOLSET="vc141"' }
194 add_default_include_paths("boost")
195 elseif os
.istarget("macosx") then
196 -- Suppress all the Boost warnings on OS X by including it as a system directory
197 buildoptions
{ "-isystem../" .. libraries_dir
.. "boost/include" }
199 -- TODO: This actually applies to most libraries we use on BSDs, make this a global setting.
200 if os
.istarget("bsd") then
201 sysincludedirs
{ "/usr/local/include" }
204 link_settings
= function()
205 if os
.istarget("windows") or os
.istarget("macosx") then
206 if os
.istarget("windows") then
207 defines
{ 'BOOST_LIB_TOOLSET="vc141"' }
209 add_default_lib_paths("boost")
212 -- The following are not strictly link dependencies on all systems, but
213 -- are included for compatibility with different versions of Boost
214 android_names
= { "boost_filesystem-gcc-mt", "boost_system-gcc-mt" },
215 unix_names
= { os
.findlib("boost_filesystem-mt") and "boost_filesystem-mt" or "boost_filesystem", os
.findlib("boost_system-mt") and "boost_system-mt" or "boost_system" },
216 osx_names
= { "boost_filesystem", "boost_system" },
221 link_settings
= function()
223 win_names
= { "comsuppw" },
230 compile_settings
= function()
231 sysincludedirs
{ libraries_source_dir
.. "cxxtest-4.4" }
235 compile_settings
= function()
236 if os
.istarget("windows") then
237 add_default_include_paths("enet")
239 pkgconfig
.add_includes("libenet")
242 link_settings
= function()
243 if os
.istarget("windows") then
244 add_default_lib_paths("enet")
246 win_names
= { "enet" },
249 pkgconfig
.add_links("libenet")
254 compile_settings
= function()
255 add_source_include_paths("fcollada")
257 link_settings
= function()
258 add_source_lib_paths("fcollada")
259 if os
.istarget("windows") then
261 links
{ "FColladaD" }
267 links
{ "FColladaSD" }
269 links
{ "FColladaSR" }
275 compile_settings
= function()
276 if os
.istarget("windows") then
277 add_default_include_paths("fmt")
278 elseif os
.istarget("macosx") then
279 pkgconfig
.add_includes("fmt")
282 -- With Linux & BSD, we assume that fmt is installed in a standard location.
284 -- It would be nice to not assume, and to instead use pkg-config: however that
285 -- requires fmt 5.3.0 or greater.
287 -- Unfortunately (at the time of writing) only 92 out of 114 (~80.7%) of distros
288 -- that provide a fmt package meet this, according to
289 -- https://repology.org/badge/vertical-allrepos/fmt.svg?minversion=5.3
291 -- Whilst that might seem like a healthy majority, this does not include the 2018
292 -- Long Term Support and 2019.10 releases of Ubuntu - not only popular and widely
293 -- used as-is, but which are also used as a base for other popular distros (e.g.
296 -- When fmt 5.3 (or better) becomes more widely used, then we can safely use the
297 -- same line as we currently use for osx
299 link_settings
= function()
300 if os
.istarget("windows") then
301 add_default_lib_paths("fmt")
303 win_names
= { "fmt" },
307 elseif os
.istarget("macosx") then
308 -- See comment above as to why this is not also used on Linux or BSD.
309 pkgconfig
.add_links("fmt")
312 unix_names
= { "fmt" },
318 compile_settings
= function()
319 if os
.istarget("windows") then
320 add_default_include_paths("freetype")
322 pkgconfig
.add_includes("freetype2")
325 link_settings
= function()
326 if os
.istarget("windows") then
327 add_default_lib_paths("freetype")
329 pkgconfig
.add_links("freetype2")
332 win_names
= { "freetype" },
338 add_source_include_paths("glad")
341 compile_settings
= function()
342 if os
.istarget("windows") then
343 add_default_include_paths("gloox")
345 pkgconfig
.add_includes("gloox")
348 link_settings
= function()
349 if os
.istarget("windows") then
350 add_default_lib_paths("gloox")
352 win_names
= { "gloox-1.0" },
356 pkgconfig
.add_links("gloox")
358 if os
.istarget("macosx") then
359 -- gloox depends on gnutls, but doesn't identify this via pkg-config
360 pkgconfig
.add_links("gnutls")
366 compile_settings
= function()
367 if os
.istarget("windows") then
368 add_default_include_paths("iconv")
369 defines
{ "HAVE_ICONV_CONST" }
370 defines
{ "ICONV_CONST=const" }
371 defines
{ "LIBICONV_STATIC" }
372 elseif os
.istarget("macosx") then
373 add_default_include_paths("iconv")
374 defines
{ "LIBICONV_STATIC" }
375 elseif os
.getversion().description
== "FreeBSD" then
376 -- On FreeBSD you need this flag to tell it to use the BSD libc iconv
377 defines
{ "LIBICONV_PLUG" }
380 link_settings
= function()
381 if os
.istarget("windows") or os
.istarget("macosx") then
382 add_default_lib_paths("iconv")
385 win_names
= { "libiconv" },
386 osx_names
= { "iconv" },
390 -- glibc (used on Linux and GNU/kFreeBSD) has iconv
394 compile_settings
= function()
395 if os
.istarget("windows") then
396 add_default_include_paths("icu")
398 pkgconfig
.add_includes("icu-i18n")
401 link_settings
= function()
402 if os
.istarget("windows") then
403 add_default_lib_paths("icu")
405 win_names
= { "icuuc", "icuin" },
410 pkgconfig
.add_links("icu-i18n")
415 compile_settings
= function()
416 if os
.istarget("windows") then
417 add_default_include_paths("libcurl")
419 pkgconfig
.add_includes("libcurl")
422 link_settings
= function()
423 if os
.istarget("windows") then
424 add_default_lib_paths("libcurl")
426 pkgconfig
.add_links("libcurl")
429 win_names
= { "libcurl" },
430 osx_frameworks
= { "Security" }, -- Not supplied by curl's pkg-config
435 compile_settings
= function()
436 if os
.istarget("windows") then
437 add_default_include_paths("libpng")
439 pkgconfig
.add_includes("libpng")
442 link_settings
= function()
443 if os
.istarget("windows") then
444 add_default_lib_paths("libpng")
446 win_names
= { "libpng16" },
449 pkgconfig
.add_links("libpng")
454 compile_settings
= function()
455 if os
.istarget("windows") then
456 add_default_include_paths("libsodium")
458 pkgconfig
.add_includes("libsodium")
461 link_settings
= function()
462 if os
.istarget("windows") then
463 add_default_lib_paths("libsodium")
465 win_names
= { "libsodium" },
468 pkgconfig
.add_links("libsodium")
473 compile_settings
= function()
474 if os
.istarget("windows") then
475 add_default_include_paths("libxml2")
477 pkgconfig
.add_includes("libxml-2.0")
479 if os
.istarget("macosx") then
480 -- libxml2 needs _REENTRANT or __MT__ for thread support;
481 -- OS X doesn't get either set by default, so do it manually
482 defines
{ "_REENTRANT" }
486 link_settings
= function()
487 if os
.istarget("windows") then
488 add_default_lib_paths("libxml2")
495 pkgconfig
.add_links("libxml-2.0")
500 compile_settings
= function()
501 if os
.istarget("windows") then
502 add_default_include_paths("miniupnpc")
503 elseif os
.istarget("macosx") then
504 pkgconfig
.add_includes("miniupnpc")
507 -- On Linux and BSD systems we assume miniupnpc is installed in a standard location.
509 -- Support for pkg-config was added in v2.1 of miniupnpc (May 2018). However, the
510 -- implementation was flawed - it provided the wrong path to the project's headers.
511 -- This was corrected in v2.2.1 (December 2020).
513 -- At the time of writing, of the 123 Linux and BSD package repositories tracked by
514 -- Repology that supply a version of miniupnpc:
515 -- * 88 (~71.54%) have >= v2.1, needed to locate libraries
516 -- * 50 (~40.65%) have >= v2.2.1, needed to (correctly) locate headers
518 -- Once more recent versions become more widespread, we can safely start to use
519 -- pkg-config to find miniupnpc on Linux and BSD systems.
520 -- https://repology.org/badge/vertical-allrepos/miniupnpc.svg?minversion=2.2.1
522 link_settings
= function()
523 if os
.istarget("windows") then
524 add_default_lib_paths("miniupnpc")
526 win_names
= { "miniupnpc" },
528 elseif os
.istarget("macosx") then
529 pkgconfig
.add_links("miniupnpc")
531 -- Once miniupnpc v2.1 or better becomes near-universal (see above comment),
532 -- we can use pkg-config for Linux and BSD.
534 unix_names
= { "miniupnpc" },
540 compile_settings
= function()
541 if not _OPTIONS
["with-system-nvtt"] then
542 add_source_include_paths("nvtt")
544 defines
{ "NVTT_SHARED=1" }
546 link_settings
= function()
547 if not _OPTIONS
["with-system-nvtt"] then
548 add_source_lib_paths("nvtt")
551 win_names
= { "nvtt" },
552 unix_names
= { "nvcore", "nvmath", "nvimage", "nvtt" },
553 osx_names
= { "bc6h", "bc7", "nvcore", "nvimage", "nvmath", "nvthread", "nvtt", "squish" },
554 dbg_suffix
= "", -- for performance we always use the release-mode version
559 compile_settings
= function()
560 if os
.istarget("windows") then
561 add_default_include_paths("openal")
562 elseif not os
.istarget("macosx") then
563 pkgconfig
.add_includes("openal")
566 link_settings
= function()
567 if os
.istarget("windows") then
568 add_default_lib_paths("openal")
570 win_names
= { "openal32" },
572 no_delayload
= 1, -- delayload seems to cause errors on startup
574 elseif os
.istarget("macosx") then
576 osx_frameworks
= { "OpenAL" },
579 pkgconfig
.add_links("openal")
584 compile_settings
= function()
585 if os
.istarget("windows") then
586 includedirs
{ libraries_dir
.. "sdl2/include/SDL" }
587 elseif not _OPTIONS
["android"] then
588 pkgconfig
.add_includes("sdl2")
591 link_settings
= function()
592 if os
.istarget("windows") then
593 add_default_lib_paths("sdl2")
594 elseif not _OPTIONS
["android"] then
595 pkgconfig
.add_links("sdl2")
600 compile_settings
= function()
601 if _OPTIONS
["with-system-mozjs"] then
602 if not _OPTIONS
["android"] then
603 pkgconfig
.add_includes("mozjs-91")
606 if os
.istarget("windows") then
607 include_dir
= "include-win32"
609 include_dir
= "include-unix"
612 sysincludedirs
{ libraries_source_dir
.."spidermonkey/"..include_dir
.."-debug" }
615 sysincludedirs
{ libraries_source_dir
.."spidermonkey/"..include_dir
.."-release" }
619 link_settings
= function()
620 if _OPTIONS
["with-system-mozjs"] then
621 if _OPTIONS
["android"] then
624 pkgconfig
.add_links("mozjs-91")
627 filter
{ "Debug", "action:vs*" }
628 links
{ "mozjs91-ps-debug" }
629 links
{ "mozjs91-ps-rust-debug" }
630 filter
{ "Debug", "action:not vs*" }
631 links
{ "mozjs91-ps-debug" }
632 links
{ "mozjs91-ps-rust" }
634 links
{ "mozjs91-ps-release" }
635 links
{ "mozjs91-ps-rust" }
637 add_source_lib_paths("spidermonkey")
642 compile_settings
= function()
643 add_third_party_include_paths("tinygettext")
647 compile_settings
= function()
648 -- Optional dependency
650 -- valgrind doesn't support windows:
651 -- https://valgrind.org/info/platforms.html
652 if _OPTIONS
["with-valgrind"] and not os
.istarget("windows") then
653 pkgconfig
.add_includes("valgrind")
654 defines
{ "CONFIG2_VALGRIND=1" }
659 compile_settings
= function()
660 if os
.istarget("windows") then
661 add_default_include_paths("vorbis")
663 pkgconfig
.add_includes("ogg")
664 pkgconfig
.add_includes("vorbisfile")
667 link_settings
= function()
668 if os
.istarget("windows") then
669 add_default_lib_paths("vorbis")
671 win_names
= { "libvorbisfile" },
673 elseif os
.getversion().description
== "OpenBSD" then
674 -- TODO: We need to force linking with these as currently
675 -- they need to be loaded explicitly on execution
677 unix_names
= { "ogg", "vorbis" },
680 pkgconfig
.add_links("vorbisfile")
685 compile_settings
= function()
686 if os
.istarget("windows") then
687 includedirs
{ libraries_dir
.."wxwidgets/include/msvc" }
688 add_default_include_paths("wxwidgets")
690 -- wxwidgets does not come with a definition file for pkg-config,
691 -- so we have to use wxwidgets' own config tool
692 wx_config_path
= os
.getenv("WX_CONFIG") or "wx-config"
693 pkgconfig
.add_includes(nil, wx_config_path
, "--unicode=yes --cxxflags")
696 link_settings
= function()
697 if os
.istarget("windows") then
698 libdirs
{ libraries_dir
.."wxwidgets/lib/vc_lib" }
700 wx_config_path
= os
.getenv("WX_CONFIG") or "wx-config"
701 pkgconfig
.add_links(nil, wx_config_path
, "--unicode=yes --libs std,gl")
706 compile_settings
= function()
707 if not os
.istarget("windows") and not os
.istarget("macosx") then
708 pkgconfig
.add_includes("x11")
711 link_settings
= function()
712 if not os
.istarget("windows") and not os
.istarget("macosx") then
713 pkgconfig
.add_links("x11")
718 compile_settings
= function()
719 if os
.istarget("windows") then
720 add_default_include_paths("zlib")
722 pkgconfig
.add_includes("zlib")
725 link_settings
= function()
726 if os
.istarget("windows") then
727 add_default_lib_paths("zlib")
729 win_names
= { "zlib1" },
733 pkgconfig
.add_links("zlib")
740 -- add a set of external libraries to the project; takes care of
741 -- include / lib path and linking against the import library.
742 -- extern_libs: table of library names [string]
743 -- target_type: String defining the projects kind [string]
744 function project_add_extern_libs(extern_libs
, target_type
)
746 for i
,extern_lib
in pairs(extern_libs
) do
747 local def
= extern_lib_defs
[extern_lib
]
748 assert(def
, "external library " .. extern_lib
.. " not defined")
750 if def
.compile_settings
then
751 def
.compile_settings()
754 -- Linking to external libraries will only be done in the main executable and not in the
755 -- static libraries. Premake would silently skip linking into static libraries for some
756 -- actions anyway (e.g. vs2010).
757 -- On osx using xcode, if this linking would be defined in the static libraries, it would fail to
758 -- link if only dylibs are available. If both *.a and *.dylib are available, it would link statically.
759 -- I couldn't find any problems with that approach.
760 if target_type
~= "StaticLib" and def
.link_settings
then