|
| 1 | +-- LLVM OpenMP runtime built from its pinned release sources. |
| 2 | +-- libomp implements the Clang and (on Unix) GCC OpenMP ABIs. Consumers enable |
| 3 | +-- OpenMP compilation themselves; this package supplies the header and runtime. |
| 4 | +-- Unix uses a static C-ABI runtime; Windows ships the upstream DLL/import lib. |
| 5 | +package = { |
| 6 | + spec = "1", |
| 7 | + namespace = "compat", |
| 8 | + name = "openmp", |
| 9 | + description = "LLVM OpenMP runtime and omp.h, built from source", |
| 10 | + licenses = {"Apache-2.0 WITH LLVM-exception"}, |
| 11 | + repo = "https://github.com/llvm/llvm-project/tree/main/openmp", |
| 12 | + type = "package", |
| 13 | + xpm = { |
| 14 | + linux = { |
| 15 | + deps = { "xim:cmake@latest", "xim:python@3.13.12" }, |
| 16 | + ["22.1.8"] = { |
| 17 | + url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/llvm-project-22.1.8.src.tar.xz", |
| 18 | + sha256 = "922f1817a0df7b1489272d18134ee0087a8b068828f87ac63b9861b1a9965888", |
| 19 | + }, |
| 20 | + }, |
| 21 | + macosx = { |
| 22 | + deps = { "xim:cmake@latest", "xim:python@3.13.12" }, |
| 23 | + ["22.1.8"] = { |
| 24 | + url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/llvm-project-22.1.8.src.tar.xz", |
| 25 | + sha256 = "922f1817a0df7b1489272d18134ee0087a8b068828f87ac63b9861b1a9965888", |
| 26 | + }, |
| 27 | + }, |
| 28 | + windows = { |
| 29 | + deps = { "xim:cmake@latest", "xim:python@3.13.12" }, |
| 30 | + ["22.1.8"] = { |
| 31 | + url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/llvm-project-22.1.8.src.tar.xz", |
| 32 | + sha256 = "922f1817a0df7b1489272d18134ee0087a8b068828f87ac63b9861b1a9965888", |
| 33 | + }, |
| 34 | + }, |
| 35 | + }, |
| 36 | + mcpp = { |
| 37 | + language = "c++23", |
| 38 | + import_std = false, |
| 39 | + c_standard = "c11", |
| 40 | + include_dirs = {"mcpp_openmp/include"}, |
| 41 | + -- Written last by install(), after CMake has installed the runtime. |
| 42 | + sources = {"mcpp_openmp_anchor.c"}, |
| 43 | + targets = {["openmp"] = {kind = "lib"}}, |
| 44 | + linux = {ldflags = {"-Lmcpp_openmp/lib", "-lomp", "-lpthread", "-ldl"}}, |
| 45 | + macosx = {ldflags = {"-Lmcpp_openmp/lib", "-lomp"}}, |
| 46 | + windows = { |
| 47 | + ldflags = {"-Lmcpp_openmp/lib", "-llibomp"}, |
| 48 | + runtime = {library_dirs = {"mcpp_openmp/bin"}}, |
| 49 | + }, |
| 50 | + deps = {}, |
| 51 | + }, |
| 52 | +} |
| 53 | + |
| 54 | +import("xim.libxpkg.pkginfo") |
| 55 | +import("xim.libxpkg.log") |
| 56 | + |
| 57 | +local function quote(value) |
| 58 | + value = tostring(value) |
| 59 | + if os.host() == "windows" then |
| 60 | + return '"' .. value:gsub('"', '\\"') .. '"' |
| 61 | + end |
| 62 | + return "'" .. value:gsub("'", "'\\''") .. "'" |
| 63 | +end |
| 64 | + |
| 65 | +local function tool(dep, name) |
| 66 | + local info = pkginfo.build_dep(dep) |
| 67 | + if info then |
| 68 | + for _, candidate in ipairs({ |
| 69 | + path.join(info.bin or info.path or "", name), |
| 70 | + path.join(info.path or "", "CMake.app", "Contents", "bin", name), |
| 71 | + }) do |
| 72 | + if os.isfile(candidate) then return candidate end |
| 73 | + end |
| 74 | + end |
| 75 | + return name |
| 76 | +end |
| 77 | + |
| 78 | +local function run(command, logfile) |
| 79 | + command = command .. " >> " .. quote(logfile) .. " 2>&1" |
| 80 | + if os.host() == "windows" then |
| 81 | + -- xlings cannot reliably invoke a quoted .exe directly on Windows. |
| 82 | + -- A batch file preserves CMake's arguments and reports its exit code. |
| 83 | + local bat = path.join(pkginfo.install_dir(), "mcpp_openmp_run.bat") |
| 84 | + io.writefile(bat, "@echo off\r\n" .. command |
| 85 | + .. "\r\nif errorlevel 1 exit /b 1\r\nexit /b 0\r\n") |
| 86 | + command = "cmd /c " .. quote(bat) |
| 87 | + end |
| 88 | + local ok, result = pcall(os.exec, command) |
| 89 | + if ok and result then return true end |
| 90 | + local lines = {} |
| 91 | + if os.isfile(logfile) then |
| 92 | + for line in (io.readfile(logfile) .. "\n"):gmatch("(.-)\n") do |
| 93 | + lines[#lines + 1] = line |
| 94 | + end |
| 95 | + end |
| 96 | + local tail = table.concat(lines, "\n", math.max(1, #lines - 59), #lines) |
| 97 | + log.error("compat.openmp: CMake failed; see %s\n%s", logfile, tail) |
| 98 | + return false |
| 99 | +end |
| 100 | + |
| 101 | +function install() |
| 102 | + local prefix = pkginfo.install_dir() |
| 103 | + local root = "llvm-project-" .. pkginfo.version() .. ".src" |
| 104 | + if not os.isdir(root) then |
| 105 | + log.error("compat.openmp: missing extracted source %s", root) |
| 106 | + return false |
| 107 | + end |
| 108 | + os.tryrm(prefix) |
| 109 | + os.mv(root, prefix) |
| 110 | + local build = path.join(prefix, "mcpp_openmp_build") |
| 111 | + local output = path.join(prefix, "mcpp_openmp") |
| 112 | + local logfile = path.join(prefix, "mcpp_openmp_build.log") |
| 113 | + local windows = os.host() == "windows" |
| 114 | + local cmake = tool("xim:cmake", windows and "cmake.exe" or "cmake") |
| 115 | + local python = tool("xim:python", windows and "python.exe" or "python3") |
| 116 | + local options = windows and ' -G "Visual Studio 17 2022" -A x64 -DLIBOMP_ENABLE_SHARED=ON' |
| 117 | + or ' -G "Unix Makefiles" -DLIBOMP_ENABLE_SHARED=OFF' |
| 118 | + if not windows then |
| 119 | + -- install() runs before consumer toolchain resolution. Build the C-ABI |
| 120 | + -- runtime with the system SDK; libomp has no C++ standard-library ABI. |
| 121 | + options = options .. " -DCMAKE_C_COMPILER=/usr/bin/cc -DCMAKE_CXX_COMPILER=/usr/bin/c++" |
| 122 | + .. " -DCMAKE_ASM_COMPILER=/usr/bin/cc -DCMAKE_MAKE_PROGRAM=/usr/bin/make" |
| 123 | + end |
| 124 | + local configure = quote(cmake) .. " -S " .. quote(path.join(prefix, "openmp")) |
| 125 | + .. " -B " .. quote(build) .. " -DCMAKE_BUILD_TYPE=Release" |
| 126 | + .. " -DCMAKE_INSTALL_PREFIX=" .. quote(output) |
| 127 | + .. " -DPython3_EXECUTABLE=" .. quote(python) |
| 128 | + .. " -DOPENMP_ENABLE_LIBOMPTARGET=OFF -DOPENMP_ENABLE_OMPT_TOOLS=OFF" |
| 129 | + .. " -DLIBOMP_OMPT_SUPPORT=OFF -DLIBOMP_USE_ITT_NOTIFY=OFF" .. options |
| 130 | + if not run(configure, logfile) then return false end |
| 131 | + if not run(quote(cmake) .. " --build " .. quote(build) .. " --config Release --parallel 4", logfile) then return false end |
| 132 | + if windows then |
| 133 | + -- The Visual Studio generator can omit the archive of upstream's |
| 134 | + -- source-less ompimp target. The DLL link already produced an import |
| 135 | + -- library for these exact exports; give install() its expected name. |
| 136 | + local expected = path.join(build, "runtime", "src", "Release", "libomp.lib") |
| 137 | + local linked = path.join(build, "runtime", "src", "Release", "libomp.dll.lib") |
| 138 | + if not os.isfile(expected) and os.isfile(linked) then |
| 139 | + os.cp(linked, expected) |
| 140 | + end |
| 141 | + end |
| 142 | + if not run(quote(cmake) .. " --install " .. quote(build) .. " --config Release", logfile) then return false end |
| 143 | + local library = path.join(output, "lib", windows and "libomp.lib" or "libomp.a") |
| 144 | + if not os.isfile(library) or not os.isfile(path.join(output, "include", "omp.h")) then |
| 145 | + log.error("compat.openmp: missing installed header/library; see %s", logfile) |
| 146 | + return false |
| 147 | + end |
| 148 | + io.writefile(path.join(prefix, "mcpp_openmp_anchor.c"), "int mcpp_compat_openmp_anchor(void) { return 0; }\n") |
| 149 | + return true |
| 150 | +end |
0 commit comments