summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2023-05-01 21:05:51 +0800
committerruki <[email protected]>2023-05-01 21:05:51 +0800
commit573319e4eff83876a558155f7c4f00886122011e (patch)
treefe6f0f73459787d28fc9fd8d0f535b473454ec80
parent21fb04a180feb12bb57677fc1e1638d185fb10f1 (diff)
improve cmake trybuild #3697
-rw-r--r--xmake/modules/private/action/trybuild/cmake.lua175
1 files changed, 144 insertions, 31 deletions
diff --git a/xmake/modules/private/action/trybuild/cmake.lua b/xmake/modules/private/action/trybuild/cmake.lua
index 4b57562c8..6e103d0dc 100644
--- a/xmake/modules/private/action/trybuild/cmake.lua
+++ b/xmake/modules/private/action/trybuild/cmake.lua
@@ -48,6 +48,18 @@ function _get_buildenv(key)
return value
end
+-- get msvc
+function _get_msvc()
+ local msvc = toolchain.load("msvc")
+ assert(msvc:check(), "vs not found!") -- we need check vs envs if it has been not checked yet
+ return msvc
+end
+
+-- get msvc run environments
+function _get_msvc_runenvs()
+ return os.joinenvs(_get_msvc():runenvs())
+end
+
-- translate paths
function _translate_paths(paths)
if is_host("windows") then
@@ -313,11 +325,68 @@ function _get_configs_for_host_toolchain(configs)
end
end
--- get configs
-function _get_configs(artifacts_dir)
+-- get cmake generator for msvc
+function _get_cmake_generator_for_msvc()
+ local vsvers =
+ {
+ ["2022"] = "17",
+ ["2019"] = "16",
+ ["2017"] = "15",
+ ["2015"] = "14",
+ ["2013"] = "12",
+ ["2012"] = "11",
+ ["2010"] = "10",
+ ["2008"] = "9"
+ }
+ local vs = _get_msvc():config("vs") or config.get("vs")
+ assert(vsvers[vs], "Unknown Visual Studio version: '" .. tostring(vs) .. "' set in project.")
+ return "Visual Studio " .. vsvers[vs] .. " " .. vs
+end
+
+-- get configs for cmake generator
+function _get_configs_for_generator(configs, opt)
+ opt = opt or {}
+ configs = configs or {}
+ local cmake_generator = opt.cmake_generator
+ if cmake_generator then
+ if cmake_generator:find("Visual Studio", 1, true) then
+ cmake_generator = _get_cmake_generator_for_msvc()
+ end
+ table.insert(configs, "-G")
+ table.insert(configs, cmake_generator)
+ elseif is_plat("mingw") and is_subhost("msys") then
+ table.insert(configs, "-G")
+ table.insert(configs, "MSYS Makefiles")
+ elseif is_plat("mingw") and is_subhost("windows") then
+ table.insert(configs, "-G")
+ table.insert(configs, "MinGW Makefiles")
+ elseif is_plat("windows") then
+ table.insert(configs, "-G")
+ table.insert(configs, _get_cmake_generator_for_msvc())
+ elseif is_plat("wasm") and is_subhost("windows") then
+ table.insert(configs, "-G")
+ table.insert(configs, "MinGW Makefiles")
+ else
+ table.insert(configs, "-G")
+ table.insert(configs, "Unix Makefiles")
+ end
+end
+
+
+-- get configs for installation
+function _get_configs_for_install(configs, opt)
+ -- @see https://cmake.org/cmake/help/v3.14/module/GNUInstallDirs.html
+ -- LIBDIR: object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
+ --
+ table.insert(configs, "-DCMAKE_INSTALL_PREFIX=" .. opt.artifacts_dir)
+ table.insert(configs, "-DCMAKE_INSTALL_LIBDIR:PATH=lib")
+end
- -- add prefix
- local configs = {"-DCMAKE_INSTALL_PREFIX=" .. artifacts_dir, "-DCMAKE_INSTALL_LIBDIR:PATH=lib"}
+-- get configs
+function _get_configs(opt)
+ local configs = {}
+ _get_configs_for_install(configs, opt)
+ _get_configs_for_generator(configs, opt)
if is_plat("windows") then
_get_configs_for_windows(configs)
elseif is_plat("android") then
@@ -350,8 +419,8 @@ function _get_configs(artifacts_dir)
-- add extra user configs
local tryconfigs = config.get("tryconfigs")
if tryconfigs then
- for _, opt in ipairs(os.argv(tryconfigs)) do
- table.insert(configs, tostring(opt))
+ for _, item in ipairs(os.argv(tryconfigs)) do
+ table.insert(configs, tostring(item))
end
end
@@ -360,6 +429,50 @@ function _get_configs(artifacts_dir)
return configs
end
+-- build for msvc
+function _build_for_msvc(opt)
+ local runenvs = _get_msvc_runenvs()
+ local msbuild = find_tool("msbuild", {envs = runenvs})
+ local slnfile = assert(find_file("*.sln", os.curdir()), "*.sln file not found!")
+ os.vexecv(msbuild.program, {slnfile, "-nologo", "-t:Build", "-m", "-p:Configuration=" .. (is_mode("debug") and "Debug" or "Release"), "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs})
+ local projfile = os.isfile("INSTALL.vcxproj") and "INSTALL.vcxproj" or "INSTALL.vcproj"
+ if os.isfile(projfile) then
+ os.vexecv(msbuild.program, {projfile, "/property:configuration=" .. (is_mode("debug") and "Debug" or "Release")}, {envs = runenvs})
+ end
+end
+
+-- build for make
+function _build_for_make(opt)
+ local argv = {"-j" .. option.get("jobs")}
+ if option.get("verbose") then
+ table.insert(argv, "VERBOSE=1")
+ end
+ if is_host("bsd") then
+ os.vexecv("gmake", argv)
+ os.vexecv("gmake", {"install"})
+ else
+ os.vexecv("make", argv)
+ os.vexecv("make", {"install"})
+ end
+end
+
+-- build for ninja
+function _build_for_ninja(opt)
+ local njob = option.get("jobs") or tostring(os.default_njob())
+ local ninja = assert(find_tool("ninja"), "ninja not found!")
+ local argv = {}
+ if option.get("diagnosis") then
+ table.insert(argv, "-v")
+ end
+ table.insert(argv, "-j")
+ table.insert(argv, njob)
+ local envs
+ if is_plat("windows") then
+ envs = _get_msvc_runenvs()
+ end
+ os.vrunv(ninja.program, argv, {envs = envs})
+end
+
-- detect build-system and configuration file
function detect()
return find_file("CMakeLists.txt", os.curdir())
@@ -373,7 +486,7 @@ function clean()
if configfile then
local oldir = os.cd(buildir)
if is_plat("windows") then
- local runenvs = toolchain.load("msvc"):runenvs()
+ local runenvs = _get_msvc_runenvs()
local msbuild = find_tool("msbuild", {envs = runenvs})
os.vexecv(msbuild.program, {configfile, "-nologo", "-t:Clean", "-p:Configuration=" .. (is_mode("debug") and "Debug" or "Release"), "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs})
else
@@ -387,43 +500,43 @@ end
-- do build
function build()
+ -- get cmake
+ local cmake = assert(find_tool("cmake"), "cmake not found!")
+
-- get artifacts directory
- local artifacts_dir = _get_artifacts_dir()
+ local opt = {}
+ opt.artifacts_dir = _get_artifacts_dir()
if not os.isdir(artifacts_dir) then
os.mkdir(artifacts_dir)
end
os.cd(_get_buildir())
- -- generate makefile
- local cmake = assert(find_tool("cmake"), "cmake not found!")
- local configfile = find_file("[mM]akefile", os.curdir()) or (is_plat("windows") and find_file("*.sln", os.curdir()))
- if not configfile or os.mtime(config.filepath()) > os.mtime(configfile) then
- os.vexecv(cmake.program, _get_configs(artifacts_dir))
- end
+ -- exists $CMAKE_GENERATOR? use it
+ opt.cmake_generator = os.getenv("CMAKE_GENERATOR")
+
+ -- do configure
+ os.vexecv(cmake.program, _get_configs(opt))
-- do build
- if is_plat("windows") then
- local runenvs = toolchain.load("msvc"):runenvs()
- local msbuild = find_tool("msbuild", {envs = runenvs})
- local slnfile = assert(find_file("*.sln", os.curdir()), "*.sln file not found!")
- os.vexecv(msbuild.program, {slnfile, "-nologo", "-t:Build", "-m", "-p:Configuration=" .. (is_mode("debug") and "Debug" or "Release"), "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs})
- local projfile = os.isfile("INSTALL.vcxproj") and "INSTALL.vcxproj" or "INSTALL.vcproj"
- if os.isfile(projfile) then
- os.vexecv(msbuild.program, {projfile, "/property:configuration=" .. (is_mode("debug") and "Debug" or "Release")}, {envs = runenvs})
+ local cmake_generator = opt.cmake_generator
+ if cmake_generator then
+ if cmake_generator:find("Visual Studio", 1, true) then
+ _build_for_msvc(opt)
+ elseif cmake_generator == "Ninja" then
+ _build_for_ninja(opt)
+ elseif cmake_generator:find("Makefiles", 1, true) then
+ _build_for_make(opt)
+ else
+ raise("unknown cmake generator(%s)!", cmake_generator)
end
else
- local argv = {"-j" .. option.get("jobs")}
- if option.get("verbose") then
- table.insert(argv, "VERBOSE=1")
- end
- if is_host("bsd") then
- os.vexecv("gmake", argv)
- os.vexecv("gmake", {"install"})
+ if is_plat("windows") then
+ _build_for_msvc(opt)
else
- os.vexecv("make", argv)
- os.vexecv("make", {"install"})
+ _build_for_make(opt)
end
end
+
cprint("output to ${bright}%s", artifacts_dir)
cprint("${color.success}build ok!")
end