This is a mirror page, please see the original page:
https://xmake.io/#/package/local_3rd_source_libraryIntegrate CMake source library
After version 2.5.8, we can also directly integrate the source library with CMakeLists.txt in our project through the package mode of xmake, instead of downloading and installing it remotely.
Related issues: #1714
For example, we have the following project structure:
├── foo
│ ├── CMakeLists.txt
│ └── src
│ ├── foo.c
│ └── foo.h
├── src
│ └── main.c
├── test.lua
└── xmake.lua
The foo directory is a static library maintained by cmake, and the root directory is maintained by xmake. We can define the package("foo")
package in xmake.lua to describe how to build the foo code library.
add_rules("mode.debug", "mode.release")
package("foo")
add_deps("cmake")
set_sourcedir(path.join(os.scriptdir(), "foo"))
on_install(function (package)
local configs = {}
table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))
table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
import("package.tools.cmake").install(package, configs)
end)
on_test(function (package)
assert(package:has_cfuncs("add", {includes = "foo.h"}))
end)
package_end()
add_requires("foo")
target("demo")
set_kind("binary")
add_files("src/main.c")
add_packages("foo")
Among them, we set the code directory location of the foo package through set_sourcedir()
, and then import the auxiliary module of package.tools.cmake
through import to call cmake to build the code, xmake will automatically obtain the generated libfoo.a and the corresponding header document.
!> If only the local source code is integrated, we don't need to set additional add_urls
and add_versions
.
For the configuration description of the package, see: Package description description.
After defining the package, we can integrate it with add_requires("foo")
and add_packages("foo")
, just like integrating remote packages.
In addition, on_test
is optional. If you want to strictly check whether the package is compiled and installed successfully, you can do some tests in it.
For a complete example, see: Library with CMakeLists
Integrate Meson source library
xmake supports the integration of more third-party source code libraries maintained by other build systems, such as meson. You only need to import and use the package.tools.meson
auxiliary building module to call meson to build them.
For example, we select a package built with meson from the xmake-repo repository as an example:
package("harfbuzz")
set_sourcedir(path.join(os.scriptdir(), "3rd/harfbuzz"))
add_deps("meson")
if not is_plat("windows") then
add_deps("freetype")
end
on_load("windows", "linux", "macosx", function (package)
if package:config("icu") then
package:add("deps", "icu4c")
end
end)
on_install("windows", "linux", "macosx", function (package)
local configs = {"-Dtests=disabled", "-Ddocs=disabled", "-Dbenchmark=disabled", "-Dcairo=disabled", "-Dfontconfig=disabled", "-Dglib=disabled", "-Dgobject= disabled"}
table.insert(configs, "-Ddefault_library=" .. (package:config("shared") and "shared" or "static"))
if package:is_plat("windows") then
table.insert(configs, "-Dfreetype=disabled")
end
import("package.tools.meson").install(package, configs)
end)
on_test(function (package)
assert(package:has_cfuncs("hb_buffer_add_utf8", {includes = "harfbuzz/hb.h"}))
end)
Integrate autoconf source library
We can also use package.tools.autoconf
to locally integrate third-party code libraries maintained by autoconf.
package("pcre2")
set_sourcedir(path.join(os.scriptdir(), "3rd/pcre2"))
add_configs("jit", {description = "Enable jit.", default = true, type = "boolean"})
add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})
on_load(function (package)
local bitwidth = package:config("bitwidth") or "8"
package:add("links", "pcre2-" .. bitwidth)
package:add("defines", "PCRE2_CODE_UNIT_WIDTH=" .. bitwidth)
if not package:config("shared") then
package:add("defines", "PCRE2_STATIC")
end
end)
on_install("macosx", "linux", "mingw", function (package)
local configs = {}
table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))
table.insert(configs, "--enable-static=" .. (package:config("shared") and "no" or "yes"))
if package:debug() then
table.insert(configs, "--enable-debug")
end
if package:config("pic") ~= false then
table.insert(configs, "--with-pic")
end
if package:config("jit") then
table.insert(configs, "--enable-jit")
end
local bitwidth = package:config("bitwidth") or "8"
if bitwidth ~= "8" then
table.insert(configs, "--disable-pcre2-8")
table.insert(configs, "--enable-pcre2-" .. bitwidth)
end
import("package.tools.autoconf").install(package, configs)
end)
on_test(function (package)
assert(package:has_cfuncs("pcre2_compile", {includes = "pcre2.h"}))
end)
Both package.tools.autoconf
and package.tools.cmake
modules can support cross-compilation platforms and toolchains such as mingw/cross/iphoneos/android, xmake will automatically pass the corresponding toolchain into it, and the user does not need to do Anything else.
Integrated Scons source library
We can also use package.tools.scons
to locally integrate third-party code libraries maintained by Scons.
package("godotcpp")
set_sourcedir(path.join(os.scriptdir(), "3rd/godotcpp"))
add_deps("scons")
add_includedirs("include", "include/core", "include/gen")
on_install("linux", "windows", "macosx", "mingw", "cygwin", "iphoneos", "android", "msys", function (package)
local configs = {"generate_bindings=yes"}
table.insert(configs, "bits=" .. ((package:is_arch("x64") or package:is_arch("x86_64")) and "64" or "32"))
if package:is_plat("windows") then
io.replace("SConstruct", "/MD", "/" .. package:config("vs_runtime"), {plain = true})
end
- this fixes an error on ios and osx (https://godotengine.org/qa/65616/problems-compiling-gdnative-c-example-on-osx)
if package:is_plat("macosx", "iphoneos") then
io.replace("SConstruct", "-std=c++14", "-std=c++17", {plain = true})
end
- fix to use correct ranlib, @see https://github.com/godotengine/godot-cpp/issues/510
if package:is_plat("android") then
io.replace("SConstruct",
[[env['AR'] = toolchain + "/bin/" + arch_info['tool_path'] + "-ar"]],
[[env['AR'] = toolchain + "/bin/" + arch_info['tool_path'] + "-ar"
env['RANLIB'] = toolchain + "/bin/" + arch_info['tool_path'] + "-ranlib"]], {plain = true})
end
import("package.tools.scons").build(package, configs)
os.cp("bin/*." .. (package:is_plat("windows") and "lib" or "a"), package:installdir("lib"))
os.cp("include/core/*.hpp", package:installdir("include/core"))
os.cp("include/gen/*.hpp", package:installdir("include/gen"))
os.cp("godot-headers/android", package:installdir("include"))
os.cp("godot-headers/arvr", package:installdir("include"))
os.cp("godot-headers/gdnative", package:installdir("include"))
os.cp("godot-headers/nativescript", package:installdir("include"))
os.cp("godot-headers/net", package:installdir("include"))
os.cp("godot-headers/pluginscript", package:installdir("include"))
os.cp("godot-headers/videodecoder", package:installdir("include"))
os.cp("godot-headers/*.h", package:installdir("include"))
end)
Integrated makefile source library
Use Nmake
We can also use package.tools.nmake
to locally integrate third-party code libraries maintained by nmake.
nmake.install
will automatically bind the msvc build environment of the current user to ensure that the user can successfully call nmake.exe, msbuild and cl.exe and other programs.
package("libxml2")
set_sourcedir(path.join(os.scriptdir(), "3rd/libxml2"))
add_includedirs("include/libxml2")
if is_plat("windows") then
add_syslinks("wsock32", "ws2_32")
end
on_load("windows", function (package)
if not package:config("shared") then
package:add("defines", "LIBXML_STATIC")
end
end)
on_install("windows", function (package)
os.cd("win32")
os.vrun("cscript configure.js iso8859x=yes iconv=no compiler=msvc cruntime=/%s debug=%s prefix=\"%s\"", package:config("vs_runtime"), package:debug( ) and "yes" or "no", package:installdir())
import("package.tools.nmake").install(package, {"/f", "Makefile.msvc"})
os.tryrm(path.join(package:installdir("lib"), "libxml2_a_dll.lib"))
if package:config("shared") then
os.tryrm(path.join(package:installdir("lib"), "libxml2_a.lib"))
else
os.tryrm(path.join(package:installdir("lib"), "libxml2.lib"))
os.tryrm(path.join(package:installdir("bin"), "libxml2.dll"))
end
end)
on_test(function (package)
assert(package:has_cfuncs("xmlNewNode", {includes = {"libxml/parser.h", "libxml/tree.h"}}))
end)
Use GnuMake
We can also use package.tools.make
to locally integrate third-party code libraries maintained by gnumake.
package("openssl")
set_sourcedir(path.join(os.scriptdir(), "3rd/openssl"))
add_links("ssl", "crypto")
if is_plat("linux", "cross") then
add_syslinks("dl")
end
on_install("linux", "macosx", function (package)
- https://wiki.openssl.org/index.php/Compilation_and_Installation#PREFIX_and_OPENSSLDIR
os.vrun("./config %s --openssldir=\"%s\" --prefix=\"%s\"", package:debug() and "--debug" or "", package:installdir (), package:installdir())
import("package.tools.make").install(package)
end)
on_test(function (package)
assert(package:has_cfuncs("SSL_new", {includes = "openssl/ssl.h"}))
end)
!> We can also directly use os.vrunv("make", {})
to call the make/gmake program to build the library.
Integrate GN source library
We can also use package.tools.gn
to natively integrate third-party code maintained by GN.
package("skia")
set_sourcedir(path.join(os.scriptdir(), "3rd/openssl"))
add_deps("gn", "ninja")
add_deps("python", {kind = "binary"})
on_install("linux", "macosx", "windows", function (package)
import("package.tools.gn").install(package)
end)
on_test(function (package)
-- TODO
end)
Here is the complete script example: Skia with GN