boost: cmake test (#5640)

* boost: cmake test

* fix windows build

* move test to single file

* add iostreams support

* support regex, locale

* use tar.gz

* support locale, python

* Use sorted libs

* support all buildable by default configs

* support all configs

* support header only config

* improve all config

* improve header only config

* add warning for mpi config

* merge to boost package

* workaround for cmake url

* boostdep: add package

* hack add_urls

* boostdep: fix c++ language

* improve xmake.lua
pull/5553/merge
star9029 3 weeks ago committed by GitHub
parent bf358b339c
commit ba8fd3c1a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 269
      packages/b/boost/b2/install.lua
  2. 94
      packages/b/boost/b2/load.lua
  3. 160
      packages/b/boost/cmake/install.lua
  4. 112
      packages/b/boost/cmake/load.lua
  5. 191
      packages/b/boost/libs.lua
  6. 19
      packages/b/boost/patches/1.86.0/find-zstd.patch
  7. 107
      packages/b/boost/test.lua
  8. 514
      packages/b/boost/xmake.lua
  9. 30
      packages/b/boostdep/port/xmake.lua
  10. 31
      packages/b/boostdep/xmake.lua

@ -0,0 +1,269 @@
import("core.tool.toolchain")
import("core.base.option")
function _get_compiler(package, toolchain)
local cxx = package:build_getenv("cxx")
if package:is_plat("macosx") then
-- we uses ld/clang++ for link stdc++ for shared libraries
-- and we need `xcrun -sdk macosx clang++` to make b2 to get `-isysroot` automatically
local cc = package:build_getenv("ld")
if cc and cc:find("clang", 1, true) and cc:find("Xcode", 1, true) then
cc = "xcrun -sdk macosx clang++"
end
return format("using darwin : : %s ;", cc)
elseif package:is_plat("windows") then
local vs_toolset = toolchain:config("vs_toolset")
local msvc_ver = ""
local win_toolset = "msvc"
if toolchain:name() == "clang-cl" then
win_toolset = "clang-win"
cxx = cxx:gsub("(clang%-cl)$", "%1.exe", 1)
msvc_ver = ""
elseif vs_toolset then
local i = vs_toolset:find("%.")
msvc_ver = i and vs_toolset:sub(1, i + 1)
end
-- Specifying a version will disable b2 from forcing tools
-- from the latest installed msvc version.
return format("using %s : %s : \"%s\" ;", win_toolset, msvc_ver, cxx:gsub("\\", "\\\\"))
else
cxx = cxx:gsub("gcc$", "g++")
cxx = cxx:gsub("gcc%-", "g++-")
cxx = cxx:gsub("clang$", "clang++")
cxx = cxx:gsub("clang%-", "clang++-")
if cxx and cxx:find("clang", 1, true) then
return format("using clang : : \"%s\" ;", cxx:gsub("\\", "/"))
else
return format("using gcc : : \"%s\" ;", cxx:gsub("\\", "/"))
end
end
end
function _config_deppath(file, depname, rule)
local dep = package:dep(depname)
local info = dep:fetch({external = false})
if info then
local includedirs = table.wrap(info.sysincludedirs or info.includedirs)
for i, dir in ipairs(includedirs) do
includedirs[i] = path.unix(dir)
end
local linkdirs = table.wrap(info.linkdirs)
for i, dir in ipairs(linkdirs) do
linkdirs[i] = path.unix(dir)
end
local links = table.wrap(info.links)
local usingstr = format("\nusing %s : %s : <include>%s <search>%s <name>%s ;",
rule, dep:version(),
table.concat(includedirs, ";"),
table.concat(linkdirs, ";"),
table.concat(links, ";"))
file:write(usingstr)
end
end
function main(package)
import("libs", {rootdir = package:scriptdir()})
-- get host toolchain
local host_toolchain
if package:is_plat("windows") then
host_toolchain = toolchain.load("msvc", {plat = "windows", arch = os.arch()})
if not host_toolchain:check() then
host_toolchain = toolchain.load("clang-cl", {plat = "windows", arch = os.arch()})
end
assert(host_toolchain:check(), "host msvc or clang-cl not found!")
end
-- force boost to compile with the desired compiler
local file = io.open("user-config.jam", "w")
if file then
file:write(_get_compiler(package, host_toolchain))
file:close()
end
local bootstrap_argv =
{
"--prefix=" .. package:installdir(),
"--libdir=" .. package:installdir("lib"),
"--without-icu"
}
if package:has_tool("cxx", "clang", "clangxx") then
table.insert(bootstrap_argv, "--with-toolset=clang")
end
if package:is_plat("windows") then
-- for bootstrap.bat, all other arguments are useless
bootstrap_argv = { "msvc" }
os.vrunv("bootstrap.bat", bootstrap_argv, {envs = host_toolchain:runenvs()})
elseif package:is_plat("mingw") and is_host("windows") then
bootstrap_argv = { "gcc" }
os.vrunv("bootstrap.bat", bootstrap_argv)
-- todo looking for better solution to fix the confict between user-config.jam and project-config.jam
io.replace("project-config.jam", "using[^\n]+", "")
else
os.vrunv("./bootstrap.sh", bootstrap_argv)
end
-- get build toolchain
local build_toolchain
local build_toolset
local runenvs
if package:is_plat("windows") then
if package:has_tool("cxx", "clang_cl") then
build_toolset = "clang-win"
build_toolchain = package:toolchain("clang-cl")
elseif package:has_tool("cxx", "clang") then
build_toolset = "clang-win"
build_toolchain = package:toolchain("clang") or package:toolchain("llvm")
elseif package:has_tool("cxx", "cl") then
build_toolset = "msvc"
build_toolchain = package:toolchain("msvc")
end
if build_toolchain then
runenvs = build_toolchain:runenvs()
end
end
local file = io.open("user-config.jam", "w")
if file then
file:write(_get_compiler(package, build_toolchain))
if package:config("lzma") then
_config_deppath(file, "xz", "lzma")
end
if package:config("zstd") then
_config_deppath(file, "zstd", "zstd")
end
if package:config("zlib") then
_config_deppath(file, "zlib", "zlib")
end
if package:config("bzip2") then
_config_deppath(file, "bzip2", "bzip2")
end
file:close()
end
os.vrun("./b2 headers")
local njobs = option.get("jobs") or tostring(os.default_njob())
local argv =
{
"--prefix=" .. package:installdir(),
"--libdir=" .. package:installdir("lib"),
"-d2",
"-j" .. njobs,
"--hash",
"-q", -- quit on first error
"--layout=tagged-1.66", -- prevent -x64 suffix in case cmake can't find it
"--user-config=user-config.jam",
"install",
"threading=" .. (package:config("multi") and "multi" or "single"),
"debug-symbols=" .. (package:debug() and "on" or "off"),
"link=" .. (package:config("shared") and "shared" or "static"),
"variant=" .. (package:is_debug() and "debug" or "release"),
"runtime-debugging=" .. (package:is_debug() and "on" or "off")
}
local cxxflags = {}
if package:config("lzma") then
if package:is_plat("windows") and not package:dep("xz"):config("shared") then
table.insert(cxxflags, "-DLZMA_API_STATIC")
end
else
table.insert(argv, "-sNO_LZMA=1")
end
if not package:config("zstd") then
table.insert(argv, "-sNO_ZSTD=1")
end
if not package:config("zlib") then
table.insert(argv, "-sNO_ZLIB=1")
end
if not package:config("bzip2") then
table.insert(argv, "-sNO_BZIP2=1")
end
if package:config("lto") then
table.insert(argv, "lto=on")
end
if package:is_arch("aarch64", "arm+.*") then
table.insert(argv, "architecture=arm")
end
if package:is_arch(".+64.*") then
table.insert(argv, "address-model=64")
else
table.insert(argv, "address-model=32")
end
local linkflags = {}
table.join2(cxxflags, table.wrap(package:config("cxflags")))
table.join2(cxxflags, table.wrap(package:config("cxxflags")))
if package:is_plat("windows") then
if package:config("shared") then
table.insert(argv, "runtime-link=shared")
elseif package:has_runtime("MT", "MTd") then
table.insert(argv, "runtime-link=static")
else
table.insert(argv, "runtime-link=shared")
end
table.insert(argv, "toolset=" .. build_toolset)
table.insert(cxxflags, "-std:c++14")
elseif package:is_plat("mingw") then
table.insert(argv, "toolset=gcc")
elseif package:is_plat("macosx") then
table.insert(argv, "toolset=darwin")
-- fix macosx arm64 build issue https://github.com/microsoft/vcpkg/pull/18529
table.insert(cxxflags, "-std=c++14")
table.insert(cxxflags, "-arch")
table.insert(cxxflags, package:arch())
local xcode = package:toolchain("xcode") or import("core.tool.toolchain").load("xcode", {plat = package:plat(), arch = package:arch()})
if xcode:check() then
local xcode_dir = xcode:config("xcode")
local xcode_sdkver = xcode:config("xcode_sdkver")
local target_minver = xcode:config("target_minver")
if xcode_dir and xcode_sdkver then
local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" .. xcode_sdkver .. ".sdk"
table.insert(cxxflags, "-isysroot")
table.insert(cxxflags, xcode_sdkdir)
end
if target_minver then
table.insert(cxxflags, "-mmacosx-version-min=" .. target_minver)
end
end
else
table.insert(cxxflags, "-std=c++14")
if package:config("pic") ~= false then
table.insert(cxxflags, "-fPIC")
end
end
if package.has_runtime and package:has_runtime("c++_shared", "c++_static") then
table.insert(cxxflags, "-stdlib=libc++")
table.insert(linkflags, "-stdlib=libc++")
if package:has_runtime("c++_static") then
table.insert(linkflags, "-static-libstdc++")
end
end
if package:config("asan") then
table.insert(cxxflags, "-fsanitize=address")
table.insert(linkflags, "-fsanitize=address")
end
if cxxflags then
table.insert(argv, "cxxflags=" .. table.concat(cxxflags, " "))
end
if linkflags then
table.insert(argv, "linkflags=" .. table.concat(linkflags, " "))
end
libs.for_each(function (libname)
if package:config("all") or package:config(libname) then
table.insert(argv, "--with-" .. libname)
end
end)
if package:is_plat("linux") then
table.insert(argv, "pch=off")
end
local ok = os.execv("./b2", argv, {envs = runenvs, try = true, stdout = "boost-log.txt"})
if ok ~= 0 then
raise("boost build failed, please check log in " .. path.join(os.curdir(), "boost-log.txt"))
end
end

@ -0,0 +1,94 @@
function _get_linkname(package, libname)
local linkname
if package:is_plat("windows") then
linkname = (package:config("shared") and "boost_" or "libboost_") .. libname
else
linkname = "boost_" .. libname
end
if libname == "python" or libname == "numpy" then
linkname = linkname .. package:config("pyver"):gsub("%p+", "")
end
if package:config("multi") then
linkname = linkname .. "-mt"
end
if package:is_plat("windows") then
if package:config("shared") then
if package:debug() then
linkname = linkname .. "-gd"
end
elseif package:config("asan") or package:has_runtime("MTd") then
linkname = linkname .. "-sgd"
elseif package:has_runtime("MT") then
linkname = linkname .. "-s"
elseif package:config("asan") or package:has_runtime("MDd") then
linkname = linkname .. "-gd"
end
else
if package:debug() then
linkname = linkname .. "-d"
end
end
return linkname
end
function main(package)
import("libs", {rootdir = package:scriptdir()})
-- we need the fixed link order
local headeronly = not package:config("all")
local sublibs = {log = {"log_setup", "log"},
python = {"python", "numpy"},
stacktrace = {"stacktrace_backtrace", "stacktrace_basic"}}
libs.for_each(function (libname)
if package:config(libname) then
headeronly = false
end
local libs = sublibs[libname]
if libs then
for _, lib in ipairs(libs) do
package:add("links", _get_linkname(package, lib))
end
else
package:add("links", _get_linkname(package, libname))
end
end)
if headeronly then
package:set("kind", "library", {headeronly = true})
end
-- disable auto-link all libs
if package:is_plat("windows") then
package:add("defines", "BOOST_ALL_NO_LIB")
end
if package:config("python") then
if not package:config("shared") then
package:add("defines", "BOOST_PYTHON_STATIC_LIB")
end
package:add("deps", "python " .. package:config("pyver") .. ".x", {configs = {headeronly = true}})
end
if package:config("zstd") then
package:add("deps", "zstd")
end
if package:config("lzma") then
package:add("deps", "xz")
end
if package:config("zlib") then
package:add("deps", "zlib")
end
if package:config("bzip2") then
package:add("deps", "bzip2")
end
if package:is_plat("windows") and package:version():le("1.85.0") then
local vs_toolset = package:toolchain("msvc"):config("vs_toolset")
if vs_toolset then
local vs_toolset_ver = import("core.base.semver").new(vs_toolset)
local minor = vs_toolset_ver:minor()
if minor and minor >= 40 then
package:add("patches", "<=1.85.0", "patches/1.85.0/fix-v144.patch", "1ba99cb2e2f03a4ba489a32596c62e1310b6c73ba4d19afa8796bcf180c84422")
end
end
end
end

@ -0,0 +1,160 @@
import("core.base.hashset")
import("core.base.option")
function _mangle_link_string(package)
local link = "boost_"
if package:is_plat("windows") and not package:config("shared") then
link = "lib" .. link
end
return link
end
-- Only get package dep version in on_install
function _add_links(package)
local suffix = _mangle_link_string(package)
local sub_libs_map = {
test = {"prg_exec_monitor", "unit_test_framework"},
serialization = {"wserialization", "serialization"},
fiber = {"fiber", "fiber_numa"},
log = {"log", "log_setup"},
stacktrace = {
"stacktrace_noop",
"stacktrace_backtrace",
"stacktrace_addr2line",
"stacktrace_basic",
"stacktrace_windbg",
"stacktrace_windbg_cached",
},
}
if package:config("python") then
local py_ver = assert(package:dep("python"):version(), "Can't get python version")
py_ver = py_ver:major() .. py_ver:minor()
-- TODO: detect numpy
sub_libs_map["python"] = {
"python" .. py_ver,
"numpy" .. py_ver,
}
end
libs.for_each(function (libname)
if not package:config(libname) then
return
end
local sub_libs = sub_libs_map[libname]
if sub_libs then
for _, sub_libname in ipairs(sub_libs) do
package:add("links", suffix .. sub_libname)
end
if libname == "test" then
-- always static
package:add("links", "libboost_test_exec_monitor")
end
else
package:add("links", suffix .. libname)
end
end)
end
function _check_links(package)
local lib_files = {}
local links = hashset.from(table.wrap(package:get("links")))
for _, libfile in ipairs(os.files(package:installdir("lib/*"))) do
local link = path.basename(libfile)
if not links:remove(link) then
table.insert(lib_files, path.filename(libfile))
end
end
links = links:to_array()
if #links ~= 0 then
-- TODO: Remove header only "link" or unsupported platform link
wprint("Missing library files\n" .. table.concat(links, "\n"))
end
if #lib_files ~= 0 then
wprint("Missing links\n" .. table.concat(lib_files, "\n"))
end
end
function _add_iostreams_configs(package, configs)
local iostreams_deps = {"zlib", "bzip2", "lzma", "zstd"}
for _, dep in ipairs(iostreams_deps) do
local config = format("-DBOOST_IOSTREAMS_ENABLE_%s=%s", dep:upper(), (package:config(dep) and "ON" or "OFF"))
table.insert(configs, config)
end
end
function _add_libs_configs(package, configs)
if not package:config("all") then
local header_only_buildable
if package:is_headeronly() then
header_only_buildable = hashset.from(libs.get_header_only_buildable())
end
local exclude_libs = {}
libs.for_each(function (libname)
if header_only_buildable and header_only_buildable:has(libname) then
-- continue
else
if not package:config(libname) then
table.insert(exclude_libs, libname)
end
end
end)
table.insert(configs, "-DBOOST_EXCLUDE_LIBRARIES=" .. table.concat(exclude_libs, ";"))
end
table.insert(configs, "-DBOOST_ENABLE_PYTHON=" .. (package:config("python") and "ON" or "OFF"))
table.insert(configs, "-DBOOST_ENABLE_MPI=" .. (package:config("mpi") and "ON" or "OFF"))
if package:config("locale") then
table.insert(configs, "-DCMAKE_CXX_STANDARD=17")
end
_add_iostreams_configs(package, configs)
local openssl = package:dep("openssl")
if openssl and not openssl:is_system() then
table.insert(configs, "-DOPENSSL_ROOT_DIR=" .. openssl:installdir())
end
end
function _add_opt(package, opt)
opt.cxflags = {}
local lzma = package:dep("xz")
if lzma and not lzma:config("shared") then
table.insert(opt.cxflags, "-DLZMA_API_STATIC")
end
if package:has_tool("cxx", "cl") then
table.insert(opt.cxflags, "/EHsc")
end
end
function main(package)
import("libs", {rootdir = package:scriptdir()})
local configs = {"-DBOOST_INSTALL_LAYOUT=system"}
table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:is_debug() and "Debug" or "Release"))
table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
if package:is_plat("windows") then
table.insert(configs, "-DCMAKE_COMPILE_PDB_OUTPUT_DIRECTORY=''")
end
_add_libs_configs(package, configs)
if option.get("verbose") then
table.insert(configs, "-DBoost_DEBUG=ON")
end
local opt = {}
_add_opt(package, opt)
import("package.tools.cmake").install(package, configs, opt)
_add_links(package)
if option.get("verbose") then
_check_links(package)
end
end

@ -0,0 +1,112 @@
function _add_defines(package)
if package:is_plat("windows") then
package:add("defines", "BOOST_ALL_NO_LIB")
end
if package:config("shared") then
package:add("defines", "BOOST_ALL_DYN_LINK")
end
end
function _recursion_enabled_dep_configs(package, libname, deps, visited_table)
if package:config(libname) and not visited_table[libname] then
visited_table[libname] = true
for _, dep_libname in ipairs(deps) do
package:config_set(dep_libname, true)
_recursion_enabled_dep_configs(package, dep_libname, libs.get_lib_deps()[dep_libname], visited_table)
end
end
end
function _auto_enabled_dep_configs(package)
-- workaround
if package:config("locale") then
package:config_set("regex", true)
end
if package:config("python") then
package:config_set("thread", true)
end
local visited_table = {}
libs.for_each_lib_deps(function (libname, deps)
_recursion_enabled_dep_configs(package, libname, deps, visited_table)
end)
end
function _add_iostreams_deps(package)
if not package:config("iostreams") then
return
end
if package:config("zlib") then
package:add("deps", "zlib")
end
if package:config("bzip2") then
package:add("deps", "bzip2")
end
if package:config("lzma") then
package:add("deps", "xz")
end
if package:config("zstd") then
package:add("deps", "zstd")
package:add("deps", (is_subhost("windows") and "pkgconf") or "pkg-config")
package:add("patches", "1.86.0", "patches/1.86.0/find-zstd.patch", "7a90f2cbf01fc26bc8a98d58468c20627974f30e45bdd4a00c52644b60af1ef6")
end
end
function _add_deps(package)
if package:config("regex") then
package:add("deps", "icu4c")
end
if package:config("locale") then
package:add("deps", "libiconv", "icu4c")
end
if package:config("python") then
package:add("deps", "python", {configs = {headeronly = true}})
end
if package:config("openssl") then
package:add("deps", "openssl >=1.1.1-a") -- same as python on_load
end
_add_iostreams_deps(package)
end
function _add_header_only_configs(package)
libs.for_each(function (libname)
package:config_set(libname, false)
end)
-- TODO: find cmake option to install header only library
-- libs.for_each_header_only_buildable_lib(function (libname)
-- package:config_set(libname, true)
-- end)
end
function main(package)
import("libs", {rootdir = package:scriptdir()})
if package:config("header_only") then
package:set("kind", "library", {headeronly = true})
_add_header_only_configs(package)
else
if package:config("all") then
package:config_set("openssl", true) -- mysql/redis require
libs.for_each(function (libname)
package:config_set(libname, true)
end)
else
_auto_enabled_dep_configs(package)
end
end
if package:config("mpi") then
-- TODO: add mpi to xrepo
package:config_set("mpi", false)
wprint("package(boost) Unsupported mpi config")
end
_add_deps(package)
_add_defines(package)
end

@ -0,0 +1,191 @@
local sorted_libs = {
"wave",
"url",
"type_erasure",
"timer",
"test",
"stacktrace",
"program_options",
"process",
"nowide",
"log",
"locale",
"json",
"iostreams",
"graph_parallel",
"mpi",
"python",
"graph",
"serialization",
"regex",
"math",
"random",
"fiber",
"filesystem",
"coroutine",
"contract",
"thread",
"date_time",
"exception",
"cobalt",
"context",
"container",
"chrono",
"system",
"charconv",
"atomic"
}
local libs_dep = {
json = {
"container",
"system"
},
python = {
"graph"
},
test = {
"exception"
},
type_erasure = {
"thread"
},
thread = {
"atomic",
"chrono",
"container",
"date_time",
"exception",
"system"
},
fiber = {
"context",
"filesystem"
},
chrono = {
"system"
},
charconv = { },
contract = {
"exception",
"thread"
},
timer = { },
wave = {
"filesystem",
"serialization"
},
stacktrace = { },
coroutine = {
"context",
"exception",
"system"
},
math = {
"random"
},
exception = { },
filesystem = {
"atomic",
"system"
},
date_time = { },
atomic = { },
url = {
"system"
},
serialization = { },
process = {
"filesystem",
"system"
},
regex = { },
container = { },
random = {
"system"
},
nowide = {
"filesystem"
},
program_options = { },
system = { },
cobalt = {
"container",
"context",
"system"
},
graph = {
"math",
"random",
"regex",
"serialization"
},
context = { },
mpi = {
"graph",
"python",
"serialization"
},
log = {
"atomic",
"date_time",
"exception",
"filesystem",
"random",
"regex",
"system",
"thread"
},
iostreams = {
"random",
"regex"
},
locale = {
"thread"
},
graph_parallel = {
"filesystem",
"graph",
"mpi",
"random",
"serialization"
}
}
local header_only_buildable = {
"graph_parallel",
"system",
"exception",
"regex",
"math",
}
function get_libs()
return sorted_libs
end
function get_lib_deps()
return libs_dep
end
function get_header_only_buildable()
return header_only_buildable
end
function for_each(lambda)
for _, libname in ipairs(get_libs()) do
lambda(libname)
end
end
function for_each_header_only_buildable_lib(lambda)
for _, libname in ipairs(get_header_only_buildable()) do
lambda(libname)
end
end
function for_each_lib_deps(lambda)
for libname, deps in pairs(get_lib_deps()) do
lambda(libname, deps)
end
end

@ -0,0 +1,19 @@
diff --git a/libs/iostreams/CMakeLists.txt b/libs/iostreams/CMakeLists.txt
index 1d8352f..01b612c 100644
--- a/libs/iostreams/CMakeLists.txt
+++ b/libs/iostreams/CMakeLists.txt
@@ -27,7 +27,13 @@ function(boost_iostreams_option name description package version found target) #
if(${name})
- find_package(${package} ${version} REQUIRED)
+ if("${package}" STREQUAL "zstd")
+ include(FindPkgConfig)
+ pkg_search_module("libzstd" REQUIRED IMPORTED_TARGET "libzstd")
+ set(target "PkgConfig::libzstd")
+ else()
+ find_package(${package} ${version} REQUIRED)
+ endif()
target_sources(boost_iostreams PRIVATE ${ARGN})
target_link_libraries(boost_iostreams PRIVATE ${target})

@ -0,0 +1,107 @@
function _iostreams(package, snippets)
if not package:config("iostreams") then
return
end
if package:config("zstd") then
table.insert(snippets,
[[
#include <boost/iostreams/filter/zstd.hpp>
#include <boost/iostreams/filtering_stream.hpp>
void test() {
boost::iostreams::filtering_ostream out;
out.push(boost::iostreams::zstd_compressor());
}
]]
)
end
if package:config("lzma") then
table.insert(snippets,
[[
#include <boost/iostreams/filter/lzma.hpp>
#include <boost/iostreams/filtering_stream.hpp>
void test() {
boost::iostreams::filtering_ostream out;
out.push(boost::iostreams::lzma_compressor());
}
]]
)
end
end
function _filesystem(package, snippets)
if package:config("filesystem") then
table.insert(snippets,
[[
#include <boost/filesystem.hpp>
#include <iostream>
void test() {
boost::filesystem::path path("/path/to/directory");
if (boost::filesystem::exists(path)) {
std::cout << "Directory exists" << std::endl;
} else {
std::cout << "Directory does not exist" << std::endl;
}
}
]]
)
end
end
function _date_time(package, snippets)
if package:config("date_time") then
table.insert(snippets,
[[
#include <boost/date_time/gregorian/gregorian.hpp>
void test() {
boost::gregorian::date d(2010, 1, 30);
}
]]
)
end
end
function _header_only(package, snippets)
table.insert(snippets,
[[
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
void test() {
std::string str("a,b");
std::vector<std::string> vec;
boost::algorithm::split(vec, str, boost::algorithm::is_any_of(","));
}
]]
)
table.insert(snippets,
[[
#include <boost/unordered_map.hpp>
void test() {
boost::unordered_map<std::string, int> map;
map["2"] = 2;
}
]]
)
end
function main(package)
local snippets = {}
if package:config("header_only") then
_header_only(package, snippets)
else
if not package:config("cmake") then
_header_only(package, snippets)
end
_iostreams(package, snippets)
_filesystem(package, snippets)
_date_time(package, snippets)
end
local opt = {configs = {languages = "c++14"}}
for _, snippet in ipairs(snippets) do
assert(package:check_cxxsnippets({test = snippet}, opt))
end
end

@ -3,18 +3,24 @@ package("boost")
set_description("Collection of portable C++ source libraries.")
set_license("BSL-1.0")
-- xrepo does not support `package:config("cmake")` in on_source to set the download url, so if you want to build with cmake, we need to `add_urls` cmake archive url at first line.
-- Users can also download the cmake archive and put it in `xmake g --pkg_searchdirs=` to avoid xrepo using a non-cmake archive url.
add_urls("https://github.com/boostorg/boost/releases/download/boost-$(version)/boost-$(version)-cmake.tar.gz", {alias = "cmake"})
add_urls("https://github.com/boostorg/boost/releases/download/boost-$(version)/boost-$(version)-b2-nodocs.tar.gz")
add_urls("https://github.com/boostorg/boost/releases/download/boost-$(version)/boost-$(version).tar.gz")
add_urls("https://github.com/xmake-mirror/boost/releases/download/boost-$(version).tar.bz2", {alias = "mirror", version = function (version)
return version .. "/boost_" .. (version:gsub("%.", "_"))
end})
add_versions("cmake:1.86.0", "c62ce6e64d34414864fef946363db91cea89c1b90360eabed0515f0eda74c75c")
add_versions("1.86.0", "2128a4c96862b5c0970c1e34d76b1d57e4a1016b80df85ad39667f30b1deba26")
add_versions("1.85.0", "f4a7d3f81b8a0f65067b769ea84135fd7b72896f4f59c7f405086c8c0dc61434")
add_versions("1.84.0", "4d27e9efed0f6f152dc28db6430b9d3dfb40c0345da7342eaa5a987dde57bd95")
add_versions("1.83.0", "0c6049764e80aa32754acd7d4f179fd5551d8172a83b71532ae093e7384e98da")
add_versions("1.82.0", "b62bd839ea6c28265af9a1f68393eda37fab3611425d3b28882d8e424535ec9d")
add_versions("1.81.0", "121da556b718fd7bd700b5f2e734f8004f1cfa78b7d30145471c526ba75a151c")
add_versions("mirror:1.80.0", "1e19565d82e43bc59209a168f5ac899d3ba471d55c7610c677d4ccf2c9c500c0")
add_versions("mirror:1.79.0", "475d589d51a7f8b3ba2ba4eda022b170e562ca3b760ee922c146b6c65856ef39")
add_versions("mirror:1.78.0", "8681f175d4bdb26c52222665793eef08490d7758529330f98d3b29dd0735bccc")
@ -26,6 +32,25 @@ package("boost")
add_versions("mirror:1.72.0", "59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722")
add_versions("mirror:1.70.0", "430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778")
add_patches("1.75.0", "patches/1.75.0/warning.patch", "43ff97d338c78b5c3596877eed1adc39d59a000cf651d0bcc678cf6cd6d4ae2e")
includes(path.join(os.scriptdir(), "libs.lua"))
for _, libname in ipairs(get_libs()) do
add_configs(libname, {description = "Enable " .. libname .. " library.", default = (libname == "filesystem"), type = "boolean"})
end
add_configs("zlib", {description = "Enable zlib for iostreams", default = false, type = "boolean"})
add_configs("bzip2", {description = "Enable bzip2 for iostreams", default = false, type = "boolean"})
add_configs("lzma", {description = "Enable lzma for iostreams", default = false, type = "boolean"})
add_configs("zstd", {description = "Enable zstd for iostreams", default = false, type = "boolean"})
add_configs("openssl", {description = "Enable openssl for mysql/redis", default = false, type = "boolean"})
add_configs("cmake", {description = "Use cmake build system", default = true, type = "boolean"})
add_configs("all", {description = "Enable all library modules support.", default = false, type = "boolean"})
add_configs("header_only", {description = "Enable header only modules", default = false, type = "boolean"})
add_configs("pyver", {description = "python version x.y, etc. 3.10 (only for b2)", default = "3.10"})
add_configs("multi", {description = "Enable multi-thread support (only for b2)", default = true, type = "boolean"})
if is_plat("mingw") and is_subhost("msys") then
add_extsources("pacman::boost")
elseif is_plat("linux") then
@ -34,483 +59,50 @@ package("boost")
add_extsources("brew::boost")
end
add_patches("1.75.0", path.join(os.scriptdir(), "patches", "1.75.0", "warning.patch"), "43ff97d338c78b5c3596877eed1adc39d59a000cf651d0bcc678cf6cd6d4ae2e")
if is_plat("linux") then
add_deps("bzip2", "zlib")
if is_plat("linux", "bsd") then
add_syslinks("pthread", "dl")
end
add_configs("pyver", {description = "python version x.y, etc. 3.10", default = "3.10"})
local libnames = {"atomic",
"charconv",
"chrono",
"cobalt",
"container",
"context",
"contract",
"coroutine",
"date_time",
"exception",
"fiber",
"filesystem",
"graph",
"graph_parallel",
"headers",
"iostreams",
"json",
"locale",
"log",
"math",
"mpi",
"nowide",
"program_options",
"python",
"random",
"regex",
"serialization",
"stacktrace",
"system",
"test",
"thread",
"timer",
"type_erasure",
"url",
"wave"}
add_configs("all", { description = "Enable all library modules support.", default = false, type = "boolean"})
add_configs("multi", { description = "Enable multi-thread support.", default = true, type = "boolean"})
for _, libname in ipairs(libnames) do
add_configs(libname, { description = "Enable " .. libname .. " library.", default = (libname == "filesystem"), type = "boolean"})
end
add_configs("zstd", {description = "enable zstd for iostreams", default = false, type = "boolean"})
add_configs("lzma", {description = "enable lzma for iostreams", default = false, type = "boolean"})
add_configs("zlib", {description = "enable zlib for iostreams", default = false, type = "boolean"})
add_configs("bzip2", {description = "enable bzip2 for iostreams", default = false, type = "boolean"})
on_load(function (package)
local function get_linkname(package, libname)
local linkname
if package:is_plat("windows") then
linkname = (package:config("shared") and "boost_" or "libboost_") .. libname
else
linkname = "boost_" .. libname
end
if libname == "python" or libname == "numpy" then
linkname = linkname .. package:config("pyver"):gsub("%p+", "")
end
if package:config("multi") then
linkname = linkname .. "-mt"
end
if package:is_plat("windows") then
if package:config("shared") then
if package:debug() then
linkname = linkname .. "-gd"
end
elseif package:config("asan") or package:has_runtime("MTd") then
linkname = linkname .. "-sgd"
elseif package:has_runtime("MT") then
linkname = linkname .. "-s"
elseif package:config("asan") or package:has_runtime("MDd") then
linkname = linkname .. "-gd"
end
else
if package:debug() then
linkname = linkname .. "-d"
end
end
return linkname
end
-- we need the fixed link order
local headeronly = not package:config("all")
local sublibs = {log = {"log_setup", "log"},
python = {"python", "numpy"},
stacktrace = {"stacktrace_backtrace", "stacktrace_basic"}}
for _, libname in ipairs(libnames) do
if package:config(libname) then
headeronly = false
end
local libs = sublibs[libname]
if libs then
for _, lib in ipairs(libs) do
package:add("links", get_linkname(package, lib))
end
else
package:add("links", get_linkname(package, libname))
end
end
if headeronly then
package:set("kind", "library", {headeronly = true})
end
-- disable auto-link all libs
if package:is_plat("windows") then
package:add("defines", "BOOST_ALL_NO_LIB")
end
if package:config("python") then
if not package:config("shared") then
package:add("defines", "BOOST_PYTHON_STATIC_LIB")
end
package:add("deps", "python " .. package:config("pyver") .. ".x", {configs = {headeronly = true}})
end
if package:config("zstd") then
package:add("deps", "zstd")
end
if package:config("lzma") then
package:add("deps", "xz")
end
if package:config("zlib") then
package:add("deps", "zlib")
end
if package:config("bzip2") then
package:add("deps", "bzip2")
end
if package:is_plat("windows") and package:version():le("1.85.0") then
local vs_toolset = package:toolchain("msvc"):config("vs_toolset")
if vs_toolset then
local vs_toolset_ver = import("core.base.semver").new(vs_toolset)
local minor = vs_toolset_ver:minor()
if minor and minor >= 40 then
package:add("patches", "<=1.85.0", "patches/1.85.0/fix-v144.patch", "1ba99cb2e2f03a4ba489a32596c62e1310b6c73ba4d19afa8796bcf180c84422")
end
end
end
end)
on_install("macosx", "linux", "windows", "bsd", "mingw", "cross", function (package)
import("core.base.option")
local function get_compiler(package, toolchain)
local cxx = package:build_getenv("cxx")
if package:is_plat("macosx") then
-- we uses ld/clang++ for link stdc++ for shared libraries
-- and we need `xcrun -sdk macosx clang++` to make b2 to get `-isysroot` automatically
local cc = package:build_getenv("ld")
if cc and cc:find("clang", 1, true) and cc:find("Xcode", 1, true) then
cc = "xcrun -sdk macosx clang++"
end
return format("using darwin : : %s ;", cc)
elseif package:is_plat("windows") then
local vs_toolset = toolchain:config("vs_toolset")
local msvc_ver = ""
local win_toolset = "msvc"
if toolchain:name() == "clang-cl" then
win_toolset = "clang-win"
cxx = cxx:gsub("(clang%-cl)$", "%1.exe", 1)
msvc_ver = ""
elseif vs_toolset then
local i = vs_toolset:find("%.")
msvc_ver = i and vs_toolset:sub(1, i + 1)
end
-- Specifying a version will disable b2 from forcing tools
-- from the latest installed msvc version.
return format("using %s : %s : \"%s\" ;", win_toolset, msvc_ver, cxx:gsub("\\", "\\\\"))
else
cxx = cxx:gsub("gcc$", "g++")
cxx = cxx:gsub("gcc%-", "g++-")
cxx = cxx:gsub("clang$", "clang++")
cxx = cxx:gsub("clang%-", "clang++-")
if cxx and cxx:find("clang", 1, true) then
return format("using clang : : \"%s\" ;", cxx:gsub("\\", "/"))
else
return format("using gcc : : \"%s\" ;", cxx:gsub("\\", "/"))
if on_check then
on_check(function (package)
if not package:is_plat("macosx", "linux", "windows", "bsd", "mingw", "cross") then
if not package:config("cmake") then
raise("package(boost/b2) unsupported current platform.")
end
end
end
-- get host toolchain
import("core.tool.toolchain")
local host_toolchain
if package:is_plat("windows") then
host_toolchain = toolchain.load("msvc", {plat = "windows", arch = os.arch()})
if not host_toolchain:check() then
host_toolchain = toolchain.load("clang-cl", {plat = "windows", arch = os.arch()})
local version = package:version()
if package:config("cmake") and version:lt("1.86") then
raise("package(boost/cmake) only support >= 1.86.0 version")
end
assert(host_toolchain:check(), "host msvc or clang-cl not found!")
end
-- force boost to compile with the desired compiler
local file = io.open("user-config.jam", "w")
if file then
file:write(get_compiler(package, host_toolchain))
file:close()
end
local bootstrap_argv =
{
"--prefix=" .. package:installdir(),
"--libdir=" .. package:installdir("lib"),
"--without-icu"
}
end)
end
if package:has_tool("cxx", "clang", "clangxx") then
table.insert(bootstrap_argv, "--with-toolset=clang")
end
on_load(function (package)
local version = package:version()
if package:config("cmake") and version:ge("1.86") then
wprint("If cmake build failure, set package config cmake = false fallback to b2 for the build")
if package:is_plat("windows") then
-- for bootstrap.bat, all other arguments are useless
bootstrap_argv = { "msvc" }
os.vrunv("bootstrap.bat", bootstrap_argv, {envs = host_toolchain:runenvs()})
elseif package:is_plat("mingw") and is_host("windows") then
bootstrap_argv = { "gcc" }
os.vrunv("bootstrap.bat", bootstrap_argv)
-- todo looking for better solution to fix the confict between user-config.jam and project-config.jam
io.replace("project-config.jam", "using[^\n]+", "")
package:add("deps", "cmake")
import("cmake.load")(package)
else
os.vrunv("./bootstrap.sh", bootstrap_argv)
end
-- get build toolchain
local build_toolchain
local build_toolset
local runenvs
if package:is_plat("windows") then
if package:has_tool("cxx", "clang_cl") then
build_toolset = "clang-win"
build_toolchain = package:toolchain("clang-cl")
elseif package:has_tool("cxx", "clang") then
build_toolset = "clang-win"
build_toolchain = package:toolchain("clang") or package:toolchain("llvm")
elseif package:has_tool("cxx", "cl") then
build_toolset = "msvc"
build_toolchain = package:toolchain("msvc")
end
if build_toolchain then
runenvs = build_toolchain:runenvs()
end
end
local function config_deppath(file, depname, rule)
local dep = package:dep(depname)
local info = dep:fetch({external = false})
if info then
local includedirs = table.wrap(info.sysincludedirs or info.includedirs)
for i, dir in ipairs(includedirs) do
includedirs[i] = path.unix(dir)
end
local linkdirs = table.wrap(info.linkdirs)
for i, dir in ipairs(linkdirs) do
linkdirs[i] = path.unix(dir)
end
local links = table.wrap(info.links)
local usingstr = format("\nusing %s : %s : <include>%s <search>%s <name>%s ;",
rule, dep:version(),
table.concat(includedirs, ";"),
table.concat(linkdirs, ";"),
table.concat(links, ";"))
file:write(usingstr)
end
end
local file = io.open("user-config.jam", "w")
if file then
file:write(get_compiler(package, build_toolchain))
if package:config("lzma") then
config_deppath(file, "xz", "lzma")
end
if package:config("zstd") then
config_deppath(file, "zstd", "zstd")
end
if package:config("zlib") then
config_deppath(file, "zlib", "zlib")
end
if package:config("bzip2") then
config_deppath(file, "bzip2", "bzip2")
if package:is_plat("linux") then
package:add("deps", "bzip2", "zlib")
end
file:close()
end
os.vrun("./b2 headers")
local njobs = option.get("jobs") or tostring(os.default_njob())
local argv =
{
"--prefix=" .. package:installdir(),
"--libdir=" .. package:installdir("lib"),
"-d2",
"-j" .. njobs,
"--hash",
"-q", -- quit on first error
"--layout=tagged-1.66", -- prevent -x64 suffix in case cmake can't find it
"--user-config=user-config.jam",
"install",
"threading=" .. (package:config("multi") and "multi" or "single"),
"debug-symbols=" .. (package:debug() and "on" or "off"),
"link=" .. (package:config("shared") and "shared" or "static"),
"variant=" .. (package:is_debug() and "debug" or "release"),
"runtime-debugging=" .. (package:is_debug() and "on" or "off")
}
local cxxflags = {}
if package:config("lzma") then
if package:is_plat("windows") and not package:dep("xz"):config("shared") then
table.insert(cxxflags, "-DLZMA_API_STATIC")
end
else
table.insert(argv, "-sNO_LZMA=1")
end
if not package:config("zstd") then
table.insert(argv, "-sNO_ZSTD=1")
end
if not package:config("zlib") then
table.insert(argv, "-sNO_ZLIB=1")
end
if not package:config("bzip2") then
table.insert(argv, "-sNO_BZIP2=1")
end
if package:config("lto") then
table.insert(argv, "lto=on")
end
if package:is_arch("aarch64", "arm+.*") then
table.insert(argv, "architecture=arm")
end
if package:is_arch(".+64.*") then
table.insert(argv, "address-model=64")
else
table.insert(argv, "address-model=32")
import("b2.load")(package)
end
end)
local linkflags = {}
table.join2(cxxflags, table.wrap(package:config("cxflags")))
table.join2(cxxflags, table.wrap(package:config("cxxflags")))
if package:is_plat("windows") then
if package:config("shared") then
table.insert(argv, "runtime-link=shared")
elseif package:has_runtime("MT", "MTd") then
table.insert(argv, "runtime-link=static")
else
table.insert(argv, "runtime-link=shared")
end
table.insert(argv, "toolset=" .. build_toolset)
table.insert(cxxflags, "-std:c++14")
elseif package:is_plat("mingw") then
table.insert(argv, "toolset=gcc")
elseif package:is_plat("macosx") then
table.insert(argv, "toolset=darwin")
-- fix macosx arm64 build issue https://github.com/microsoft/vcpkg/pull/18529
table.insert(cxxflags, "-std=c++14")
table.insert(cxxflags, "-arch")
table.insert(cxxflags, package:arch())
local xcode = package:toolchain("xcode") or import("core.tool.toolchain").load("xcode", {plat = package:plat(), arch = package:arch()})
if xcode:check() then
local xcode_dir = xcode:config("xcode")
local xcode_sdkver = xcode:config("xcode_sdkver")
local target_minver = xcode:config("target_minver")
if xcode_dir and xcode_sdkver then
local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" .. xcode_sdkver .. ".sdk"
table.insert(cxxflags, "-isysroot")
table.insert(cxxflags, xcode_sdkdir)
end
if target_minver then
table.insert(cxxflags, "-mmacosx-version-min=" .. target_minver)
end
end
on_install(function (package)
local version = package:version()
if package:config("cmake") and version:ge("1.86") then
assert(os.isfile("CMakeLists.txt"), "Currently the source archive only has the b2 build system, you need to download the cmake archive and put it in `xmake g --pkg_searchdirs=` to avoid xrepo using a non-cmake archive url.")
import("cmake.install")(package)
else
table.insert(cxxflags, "-std=c++14")
if package:config("pic") ~= false then
table.insert(cxxflags, "-fPIC")
end
end
if package.has_runtime and package:has_runtime("c++_shared", "c++_static") then
table.insert(cxxflags, "-stdlib=libc++")
table.insert(linkflags, "-stdlib=libc++")
if package:has_runtime("c++_static") then
table.insert(linkflags, "-static-libstdc++")
end
end
if package:config("asan") then
table.insert(cxxflags, "-fsanitize=address")
table.insert(linkflags, "-fsanitize=address")
end
if cxxflags then
table.insert(argv, "cxxflags=" .. table.concat(cxxflags, " "))
end
if linkflags then
table.insert(argv, "linkflags=" .. table.concat(linkflags, " "))
end
for _, libname in ipairs(libnames) do
if package:config("all") or package:config(libname) then
table.insert(argv, "--with-" .. libname)
end
end
if package:is_plat("linux") then
table.insert(argv, "pch=off")
end
local ok = os.execv("./b2", argv, {envs = runenvs, try = true, stdout = "boost-log.txt"})
if ok ~= 0 then
raise("boost build failed, please check log in " .. path.join(os.curdir(), "boost-log.txt"))
import("b2.install")(package)
end
end)
on_test(function (package)
assert(package:check_cxxsnippets({test = [[
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
static void test() {
std::string str("a,b");
std::vector<std::string> vec;
boost::algorithm::split(vec, str, boost::algorithm::is_any_of(","));
}
]]}, {configs = {languages = "c++14"}}))
assert(package:check_cxxsnippets({test = [[
#include <boost/unordered_map.hpp>
static void test() {
boost::unordered_map<std::string, int> map;
map["2"] = 2;
}
]]}, {configs = {languages = "c++14"}}))
if package:config("date_time") then
assert(package:check_cxxsnippets({test = [[
#include <boost/date_time/gregorian/gregorian.hpp>
static void test() {
boost::gregorian::date d(2010, 1, 30);
}
]]}, {configs = {languages = "c++14"}}))
end
if package:config("filesystem") then
assert(package:check_cxxsnippets({test = [[
#include <boost/filesystem.hpp>
#include <iostream>
static void test() {
boost::filesystem::path path("/path/to/directory");
if (boost::filesystem::exists(path)) {
std::cout << "Directory exists" << std::endl;
} else {
std::cout << "Directory does not exist" << std::endl;
}
}
]]}, {configs = {languages = "c++14"}}))
end
if package:config("iostreams") then
if package:config("zstd") then
assert(package:check_cxxsnippets({test = [[
#include <boost/iostreams/filter/zstd.hpp>
#include <boost/iostreams/filtering_stream.hpp>
static void test() {
boost::iostreams::filtering_ostream out;
out.push(boost::iostreams::zstd_compressor());
}
]]}, {configs = {languages = "c++14"}}))
end
if package:config("lzma") then
assert(package:check_cxxsnippets({test = [[
#include <boost/iostreams/filter/lzma.hpp>
#include <boost/iostreams/filtering_stream.hpp>
static void test() {
boost::iostreams::filtering_ostream out;
out.push(boost::iostreams::lzma_compressor());
}
]]}, {configs = {languages = "c++14"}}))
end
end
import("test")(package)
end)

@ -0,0 +1,30 @@
-- Boost Root build
add_rules("mode.debug", "mode.release")
set_languages("c++17")
target("filesystem")
set_kind("static")
add_files("libs/filesystem/src/*.cpp|windows_file_codecvt.cpp")
add_defines("BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF")
add_defines("BOOST_FILESYSTEM_STATIC_LINK=1", {public = true})
for _, dir in ipairs(os.dirs("libs/*")) do
add_includedirs(path.join(dir, "include"), {public = true})
end
if is_plat("windows", "mingw", "msys2") then
add_files("libs/filesystem/src/*.cpp")
add_defines("BOOST_USE_WINDOWS_H", "WIN32_LEAN_AND_MEAN", "NOMINMAX")
add_syslinks("bcrypt")
if is_plat("windows") then
add_defines("BOOST_ALL_NO_LIB", {public = true})
end
end
target("boostdep")
set_kind("binary")
add_files("tools/boostdep/src/*.cpp")
add_deps("filesystem")

@ -0,0 +1,31 @@
package("boostdep")
set_kind("binary")
set_homepage("https://boost.org/tools/boostdep")
set_description("A tool to create Boost module dependency reports")
set_license("BSL-1.0")
add_urls("https://github.com/boostorg/boostdep.git")
add_versions("2024.10.07", "289f2a16286e62348676f2abb75c0bd9968f156b")
add_deps("boost", {configs = {filesystem = true}})
on_install(function (package)
io.writefile("xmake.lua", [[
add_rules("mode.debug", "mode.release")
add_requires("boost", {configs = {filesystem = true}})
add_packages("boost")
set_languages("c++17")
target("boostdep")
set_kind("binary")
add_files("src/*.cpp")
]])
import("package.tools.xmake").install(package)
end)
on_test(function (package)
local boostdep = package:installdir("bin/boostdep")
if is_host("windows") then
boostdep = boostdep .. ".exe"
end
assert(os.isexec(boostdep), "boostdep not found!")
end)
Loading…
Cancel
Save