1- import { tmpdir } from "os"
21import path , { delimiter , join } from "path"
32import { fileURLToPath } from "url"
4- import { execRootSync } from "admina"
53import ciInfo from "ci-info"
64const { GITHUB_ACTIONS } = ciInfo
75import { info , warning } from "ci-log"
86import { addEnv } from "envosman"
97import memoize from "memoizee"
10- import { DownloaderHelper } from "node-downloader-helper"
118import { pathExists } from "path-exists"
129import { addExeExt } from "patha"
13- import { addUpdateAlternativesToRc , installAptPack } from "setup-apt"
10+ import { addUpdateAlternativesToRc } from "setup-apt"
1411import { rcOptions } from "../cli-options.js"
1512import { setupGcc } from "../gcc/gcc.js"
1613import { setupMacOSSDK } from "../macos-sdk/macos-sdk.js"
17- import { arm64 , x86_64 } from "../utils/env/arch.js"
18- import { hasDnf } from "../utils/env/hasDnf.js"
19- import { isArch } from "../utils/env/isArch.js"
2014import { isUbuntu } from "../utils/env/isUbuntu.js"
2115import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
22- import { type InstallationInfo , setupBin } from "../utils/setup/setupBin.js"
23- import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
24- import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
25- import { semverCoerceIfInvalid } from "../utils/setup/version.js"
16+ import type { InstallationInfo } from "../utils/setup/setupBin.js"
2617import { quoteIfHasSpace } from "../utils/std/index.js"
2718import { getVersion } from "../versions/versions.js"
28- import { LLVMPackages , setupLLVMApt } from "./llvm_installer.js"
29- import { getLLVMPackageInfo } from "./llvm_url.js"
19+ import { LLVMPackages , trySetupLLVMApt } from "./llvm_apt_installer.js"
20+ import { setupLLVMBin } from "./llvm_bin.js"
21+ import { majorLLVMVersion } from "./utils.js"
3022
3123const dirname = typeof __dirname === "string" ? __dirname : path . dirname ( fileURLToPath ( import . meta. url ) )
3224
@@ -44,110 +36,34 @@ async function setupLLVMWithoutActivation_(version: string, setupDir: string, ar
4436 ] )
4537
4638 // install LLVM dependencies
47- await setupLLVMDeps ( arch )
39+ await setupGccForLLVM ( arch )
4840
4941 return installationInfo
5042}
5143const setupLLVMWithoutActivation = memoize ( setupLLVMWithoutActivation_ , { promise : true } )
5244
53- /**
54- * Setup clang-format
55- *
56- * This uses the LLVM installer on Ubuntu, and the LLVM binaries on other platforms
57- */
58- export function setupClangFormat ( version : string , setupDir : string , arch : string ) {
59- return setupLLVMOnly ( version , setupDir , arch , LLVMPackages . ClangFormat )
60- }
61-
62- /** Setup llvm tools (clang tidy, etc.) without activating llvm and using it as the compiler */
63- export function setupClangTools ( version : string , setupDir : string , arch : string ) {
64- return setupLLVMOnly ( version , setupDir , arch )
65- }
66-
6745async function setupLLVMOnly (
6846 version : string ,
6947 setupDir : string ,
7048 arch : string ,
7149 packages : LLVMPackages = LLVMPackages . All ,
7250) {
73- const majorVersion = majorLLVMVersion ( version )
74- if ( isUbuntu ( ) ) {
75- try {
76- return await setupLLVMApt ( majorVersion , packages )
77- } catch ( err ) {
78- info ( `Failed to install llvm via system package manager ${ err } . Trying to remove the repository` )
79- try {
80- execRootSync ( join ( dirname , "llvm_repo_remove.bash" ) , [ `${ majorVersion } ` ] )
81- } catch ( removeErr ) {
82- info ( `Failed to remove llvm repository ${ removeErr } ` )
83- }
84- }
51+ const aptInstallInfo = await trySetupLLVMApt ( version , packages )
52+ if ( aptInstallInfo !== undefined ) {
53+ return aptInstallInfo
8554 }
8655
87- const installationInfo = await setupBin ( "llvm" , version , getLLVMPackageInfo , setupDir , arch )
88- await llvmBinaryDeps ( majorVersion )
89- return installationInfo
90- }
91-
92- function majorLLVMVersion ( version : string ) {
93- const coeredVersion = semverCoerceIfInvalid ( version )
94- return Number . parseInt ( coeredVersion . split ( "." ) [ 0 ] , 10 )
56+ return setupLLVMBin ( version , setupDir , arch )
9557}
9658
97- async function llvmBinaryDeps_ ( _majorVersion : number ) {
98- if ( isUbuntu ( ) ) {
99- for ( const dep of [ "libtinfo5" , "libtinfo6" ] ) {
100- /* eslint-disable no-await-in-loop */
101- try {
102- await installAptPack ( [ { name : dep } ] )
103- } catch ( _err ) {
104- try {
105- if ( dep === "libtinfo5" ) {
106- // Manually install libtinfo5 if the package is not available
107- info ( `Failed to install ${ dep } \nManually installing the package` )
108- const arch = x86_64 . includes ( process . arch )
109- ? "amd64"
110- : arm64 . includes ( process . arch )
111- ? "arm64"
112- : process . arch
113-
114- const fileName = `libtinfo5_6.3-2ubuntu0.1_${ arch } .deb`
115- const url = `http://launchpadlibrarian.net/666971015/${ fileName } `
116- const dl = new DownloaderHelper ( url , tmpdir ( ) , { fileName } )
117- dl . on ( "error" , async ( dlErr ) => {
118- info ( `Failed to download ${ url } : ${ dlErr } ` )
119- await dl . stop ( )
120- } )
121- await dl . start ( )
122- // Install the downloaded package via dpkg
123- execRootSync ( "dpkg" , [ "-i" , join ( tmpdir ( ) , fileName ) ] )
124- }
125- } catch ( _errFallback ) {
126- info ( `Failed to install ${ dep } . Ignoring` )
127- }
128- }
129- /* eslint-enable no-await-in-loop */
130- }
131- } else if ( isArch ( ) ) {
132- // https://aur.archlinux.org/packages/ncurses5-compat-libs
133- await setupPacmanPack ( "ncurses5-compat-libs" , undefined , "yay" )
134- } else if ( hasDnf ( ) ) {
135- // https://packages.fedoraproject.org/pkgs/ncurses/ncurses-compat-libs/index.html
136- await setupDnfPack ( [
137- { name : "ncurses-compat-libs" } ,
138- ] )
139- }
140- }
141- const llvmBinaryDeps = memoize ( llvmBinaryDeps_ , { promise : true } )
142-
143- async function setupLLVMDeps_ ( arch : string ) {
59+ async function setupGccForLLVM_ ( arch : string ) {
14460 if ( process . platform === "linux" ) {
14561 // using llvm requires ld, an up to date libstdc++, etc. So, install gcc first,
14662 // but with a lower priority than the one used by activateLLVM()
14763 await setupGcc ( getVersion ( "gcc" , undefined , await ubuntuVersion ( ) ) , "" , arch , 40 )
14864 }
14965}
150- const setupLLVMDeps = memoize ( setupLLVMDeps_ , { promise : true } )
66+ const setupGccForLLVM = memoize ( setupGccForLLVM_ , { promise : true } )
15167
15268export async function activateLLVM ( directory : string , version : string ) {
15369 const ld = process . env . LD_LIBRARY_PATH ?? ""
@@ -201,11 +117,26 @@ export async function activateLLVM(directory: string, version: string) {
201117}
202118
203119async function addLLVMLoggingMatcher ( ) {
204- if ( GITHUB_ACTIONS ) {
205- const matcherPath = join ( dirname , "llvm_matcher.json" )
206- if ( ! ( await pathExists ( matcherPath ) ) ) {
207- return warning ( "the llvm_matcher.json file does not exist in the same folder as setup-cpp.js" )
208- }
209- info ( `::add-matcher::${ matcherPath } ` )
120+ if ( ! GITHUB_ACTIONS ) {
121+ return
210122 }
123+ const matcherPath = join ( dirname , "llvm_matcher.json" )
124+ if ( ! ( await pathExists ( matcherPath ) ) ) {
125+ return warning ( "the llvm_matcher.json file does not exist in the same folder as setup-cpp.js" )
126+ }
127+ info ( `::add-matcher::${ matcherPath } ` )
128+ }
129+
130+ /**
131+ * Setup clang-format
132+ *
133+ * This uses the LLVM installer on Ubuntu, and the LLVM binaries on other platforms
134+ */
135+ export function setupClangFormat ( version : string , setupDir : string , arch : string ) {
136+ return setupLLVMOnly ( version , setupDir , arch , LLVMPackages . ClangFormat )
137+ }
138+
139+ /** Setup llvm tools (clang tidy, etc.) without activating llvm and using it as the compiler */
140+ export function setupClangTools ( version : string , setupDir : string , arch : string ) {
141+ return setupLLVMOnly ( version , setupDir , arch )
211142}
0 commit comments