summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-10-12 00:31:46 +0800
committerruki <[email protected]>2021-10-12 00:31:46 +0800
commit732ac08c207edf9baca28424a428e26d24f0032f (patch)
tree6da684300bae3d3d9e6ff72de7f5d5c6588c8086
parentb994f9c2c9d883414728b09a5990e10fb47f24c0 (diff)
improve cmake/find_package
-rw-r--r--xmake/modules/package/manager/cmake/find_package.lua157
1 files changed, 79 insertions, 78 deletions
diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua
index 7c4cc3df0..653f69f16 100644
--- a/xmake/modules/package/manager/cmake/find_package.lua
+++ b/xmake/modules/package/manager/cmake/find_package.lua
@@ -30,6 +30,7 @@ function _find_package(cmake, name, opt)
local workdir = os.tmpfile() .. ".dir"
os.tryrm(workdir)
os.mkdir(workdir)
+ io.writefile(path.join(workdir, "test.cpp"), "")
-- generate CMakeLists.txt
local cmakefile = io.open(path.join(workdir, "CMakeLists.txt"), "w")
@@ -58,107 +59,106 @@ function _find_package(cmake, name, opt)
if opt.presets then
for k, v in ipairs(opt.presets) do
if type(v) == "boolean" then
- cmakefile:print("set(%s_%s %s)", name, k, v and "ON" or "OFF")
+ cmakefile:print("set(%s %s)", k, v and "ON" or "OFF")
else
- cmakefile:print("set(%s_%s %s)", name, k, tostring(v))
+ cmakefile:print("set(%s %s)", k, tostring(v))
end
end
end
cmakefile:print("find_package(%s REQUIRED)", requirestr)
cmakefile:print("if(%s_FOUND)", name)
- for _, macro_name in ipairs({name, name:upper()}) do
- cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" \"${%s_INCLUDE_DIR}\")", macro_name, macro_name)
- cmakefile:print(" message(STATUS \"%s_INCLUDE_DIRS=\" \"${%s_INCLUDE_DIRS}\")", macro_name, macro_name)
- cmakefile:print(" message(STATUS \"%s_LIBRARY_DIR=\" \"${%s_LIBRARY_DIR}\")", macro_name, macro_name)
- cmakefile:print(" message(STATUS \"%s_LIBRARY_DIRS=\" \"${%s_LIBRARY_DIRS}\")", macro_name, macro_name)
- cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macro_name, macro_name)
- cmakefile:print(" message(STATUS \"%s_LIBRARIES=\" \"${%s_LIBRARIES}\")", macro_name, macro_name)
- cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macro_name, macro_name)
- end
+ cmakefile:print(" add_executable(%s test.cpp)", name)
+ cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})",
+ name, name, name)
+ cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})",
+ name, name:upper(), name:upper())
+ cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})",
+ name, name, name, name)
+ cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})",
+ name, name:upper(), name:upper(), name:upper())
cmakefile:print("endif(%s_FOUND)", name)
cmakefile:close()
- -- run cmake to get output
+ -- run cmake
+ try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir}) end}
+
+ -- pares includedirs
local links
local linkdirs
+ local libfiles
local includedirs
- local output, errors = try {function() return os.iorunv(cmake.program, {workdir}, {curdir = workdir}) end}
- if output then
- for _, line in ipairs(output:split("\n", {plain = true})) do
- for _, macro_name in ipairs({name, name:upper()}) do
- -- parse includedirs
- for _, includedir_key in ipairs({macro_name .. "_INCLUDE_DIR=", macro_name .. "_INCLUDE_DIRS="}) do
- if line:find(includedir_key, 1, true) then
- local splitinfo = line:split(includedir_key)
- local values = splitinfo[2]
- if values then
- values = values:split(';', {plain = true})
- end
- if values then
- includedirs = includedirs or {}
- table.join2(includedirs, values)
+ local flagsfile = path.join(workdir, "CMakeFiles", name .. ".dir", "flags.make")
+ if os.isfile(flagsfile) then
+ local flagsdata = io.readfile(flagsfile)
+ if flagsdata then
+ if option.get("diagnosis") then
+ vprint(flagsdata)
+ end
+ for _, line in ipairs(flagsdata:split("\n", {plain = true})) do
+ if line:find("CXX_INCLUDES =", 1, true) then
+ local has_include = false
+ local flags = os.argv(line:split("=", {plain = true})[2]:trim())
+ for _, flag in ipairs(flags) do
+ if has_include or (flag:startswith("-I") and #flag > 2) then
+ local includedir = has_include and flag or flag:sub(3)
+ if includedir and os.isdir(includedir) then
+ includedirs = includedirs or {}
+ table.insert(includedirs, includedir)
+ end
+ has_include = false
+ elseif flag == "-isystem" or flag == "-I" then
+ has_include = true
end
end
end
+ end
+ end
+ end
- -- parse linkdirs
- for _, linkdir_key in ipairs({macro_name .. "_LIBRARY_DIR=", macro_name .. "_LIBRARY_DIRS="}) do
- if line:find(linkdir_key, 1, true) then
- local splitinfo = line:split(linkdir_key)
- local values = splitinfo[2]
- if values then
- values = values:split(';', {plain = true})
- end
- if values then
- linkdirs = linkdirs or {}
- table.join2(linkdirs, values)
- end
+ -- parse links and linkdirs
+ local linkfile = path.join(workdir, "CMakeFiles", name .. ".dir", "link.txt")
+ if os.isfile(linkfile) then
+ local linkdata = io.readfile(linkfile)
+ if linkdata then
+ if option.get("diagnosis") then
+ vprint(linkdata)
+ end
+ for _, line in ipairs(os.argv(linkdata)) do
+ local is_library = false
+ for _, suffix in ipairs({".so", ".dylib", ".dylib", ".tbd", ".lib"}) do
+ if line:find(suffix, 1, true) then
+ is_library = true
+ break
end
end
+ if is_library then
+ -- strip library version suffix, e.g. libxxx.so.1.1 -> libxxx.so
+ if line:find(".so", 1, true) then
+ line = line:gsub("lib(.-)%.so%..+$", "lib%1.so")
+ end
- -- parse links and linkdirs
- for _, library_key in ipairs({macro_name .. "_LIBRARY=", macro_name .. "_LIBS=", macro_name .. "_LIBRARIES="}) do
- if line:find(library_key, 1, true) then
- local splitinfo = line:split(library_key)
- local values = splitinfo[2]
- if values then
- values = values:split(';', {plain = true})
- end
- for _, library in ipairs(values) do
- local linkdir = path.directory(library)
- if linkdir ~= "." then
- linkdirs = linkdirs or {}
- table.insert(linkdirs, linkdir)
- end
- local link = target.linkname(path.filename(library))
- if not link then
- -- has been link name?
- if path.filename(library) == path.basename(library) and linkdir == "." then
- link = library
- end
- end
- if link then
- assert(not link:find("::", 1, true), "link(%s) is not supported yet!", link)
- links = links or {}
- table.insert(links, link)
- end
- end
+ -- get libfiles
+ if os.isfile(line) then
+ libfiles = libfiles or {}
+ table.insert(libfiles, line)
+ end
+
+ -- get links and linkdirs
+ local linkdir = path.directory(line)
+ if linkdir ~= "." then
+ linkdirs = linkdirs or {}
+ table.insert(linkdirs, linkdir)
+ end
+ local link = target.linkname(path.filename(line))
+ if link then
+ links = links or {}
+ table.insert(links, link)
end
end
end
end
end
- -- trace diagnosis info
- if option.get("verbose") then
- if output then
- print(output)
- end
- if option.get("diagnosis") and errors and errors:trim() ~= "" then
- cprint("${color.warning}checkinfo: ${clear dim}" .. errors)
- end
- end
-
-- remove work directory
os.tryrm(workdir)
@@ -167,6 +167,7 @@ function _find_package(cmake, name, opt)
local results = {}
results.links = table.reverse_unique(links)
results.linkdirs = table.unique(linkdirs)
+ results.libfiles = table.unique(libfiles)
results.includedirs = table.unique(includedirs)
return results
end
@@ -178,14 +179,14 @@ end
--
-- find_package("cmake::ZLIB")
-- find_package("cmake::OpenCV", {required_version = "4.1.1"})
--- find_package("cmake::Boost", {components = {"regex", "system"}, presets = {USE_STATIC_LIB = true}})
+-- find_package("cmake::Boost", {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}})
-- find_package("cmake::Foo", {moduledirs = "xxx"})
--
-- @param name the package name
-- @param opt the options, e.g. {verbose = true, required_version = "1.0",
-- components = {"regex", "system"},
-- moduledirs = "xxx",
--- presets = {USE_STATIC_LIB = true})
+-- presets = {Boost_USE_STATIC_LIB = true})
--
function main(name, opt)
opt = opt or {}