diff options
| author | ruki <[email protected]> | 2021-10-12 00:31:46 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2021-10-12 00:31:46 +0800 |
| commit | 732ac08c207edf9baca28424a428e26d24f0032f (patch) | |
| tree | 6da684300bae3d3d9e6ff72de7f5d5c6588c8086 | |
| parent | b994f9c2c9d883414728b09a5990e10fb47f24c0 (diff) | |
improve cmake/find_package
| -rw-r--r-- | xmake/modules/package/manager/cmake/find_package.lua | 157 |
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 {} |
