@@ -16,6 +16,7 @@ const pipeline = promisify(stream.pipeline);
1616
1717const win32BatPath = path . join ( __dirname , "build-openssl.bat" ) ;
1818const vendorPath = path . resolve ( __dirname , ".." , "vendor" ) ;
19+ const opensslPatchPath = path . join ( vendorPath , "patches" , "openssl" ) ;
1920const extractPath = path . join ( vendorPath , "openssl" ) ;
2021
2122const getOpenSSLSourceUrl = ( version ) => `https://www.openssl.org/source/openssl-${ version } .tar.gz` ;
@@ -27,7 +28,7 @@ class HashVerify extends stream.Transform {
2728 this . expected = expected ;
2829 this . hash = crypto . createHash ( algorithm ) ;
2930 }
30-
31+
3132 _transform ( chunk , encoding , callback ) {
3233 this . hash . update ( chunk , encoding ) ;
3334 callback ( null , chunk ) ;
@@ -40,28 +41,95 @@ class HashVerify extends stream.Transform {
4041 }
4142}
4243
44+ // currently this only needs to be done on linux
45+ const applyOpenSSLPatches = async ( buildCwd ) => {
46+ try {
47+ for ( const patchFilename of await fse . readdir ( opensslPatchPath ) ) {
48+ if ( patchFilename . split ( "." ) . pop ( ) === "patch" ) {
49+ console . log ( `applying ${ patchFilename } ` ) ;
50+ await execPromise ( `patch -up0 -i ${ path . join ( opensslPatchPath , patchFilename ) } ` , {
51+ cwd : buildCwd
52+ } , { pipeOutput : true } ) ;
53+ }
54+ }
55+ } catch ( e ) {
56+ console . log ( "Patch application failed: " , e ) ;
57+ throw e ;
58+ }
59+ }
60+
4361const buildDarwin = async ( buildCwd , macOsDeploymentTarget ) => {
44- const triplet = process . arch === 'x64'
45- ? 'darwin64-x86_64-cc'
46- : 'darwin64-arm64-cc' ;
47-
48- await execPromise ( `./Configure ${
49- triplet
50- } no-shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --prefix="${
51- extractPath
52- } " --openssldir="${ extractPath } " -mmacosx-version-min=${ macOsDeploymentTarget } `, {
62+ const arguments = [
63+ process . arch === "x64" ? "darwin64-x86_64-cc" : "darwin64-arm64-cc" ,
64+ // speed up ecdh on little-endian platforms with 128bit int support
65+ "enable-ec_nistp_64_gcc_128" ,
66+ // compile static libraries
67+ "no-shared" ,
68+ // disable ssl2, ssl3, and compression
69+ "no-ssl2" ,
70+ "no-ssl3" ,
71+ "no-comp" ,
72+ // set install directory
73+ `--prefix="${ extractPath } "` ,
74+ `--openssldir="${ extractPath } "` ,
75+ // set macos version requirement
76+ `-mmacosx-version-min=${ macOsDeploymentTarget } `
77+ ] ;
78+
79+ await execPromise ( `./Configure ${ arguments . join ( " " ) } ` , {
5380 cwd : buildCwd
5481 } , { pipeOutput : true } ) ;
5582
56- await execPromise ( "make" , {
83+ // only build the libraries, not the tests/fuzzer or apps
84+ await execPromise ( "make build_libs" , {
5785 cwd : buildCwd
5886 } , { pipeOutput : true } ) ;
5987
6088 await execPromise ( "make test" , {
6189 cwd : buildCwd
6290 } , { pipeOutput : true } ) ;
6391
64- await execPromise ( "make install" , {
92+ await execPromise ( "make install_sw" , {
93+ cwd : buildCwd ,
94+ maxBuffer : 10 * 1024 * 1024 // we should really just use spawn
95+ } , { pipeOutput : true } ) ;
96+ } ;
97+
98+ const buildLinux = async ( buildCwd ) => {
99+ const arguments = [
100+ "linux-x86_64" ,
101+ // Electron(at least on centos7) imports the libcups library at runtime, which has a
102+ // dependency on the system libssl/libcrypto which causes symbol conflicts and segfaults.
103+ // To fix this we need to hide all the openssl symbols to prevent them from being overridden
104+ // by the runtime linker.
105+ "-fvisibility=hidden" ,
106+ // compile static libraries
107+ "no-shared" ,
108+ // disable ssl2, ssl3, and compression
109+ "no-ssl2" ,
110+ "no-ssl3" ,
111+ "no-comp" ,
112+ // set install directory
113+ `--prefix="${ extractPath } "` ,
114+ `--openssldir="${ extractPath } "`
115+ ] ;
116+ await execPromise ( `./Configure ${ arguments . join ( " " ) } ` , {
117+ cwd : buildCwd
118+ } , { pipeOutput : true } ) ;
119+
120+ await applyOpenSSLPatches ( buildCwd ) ;
121+
122+ // only build the libraries, not the tests/fuzzer or apps
123+ await execPromise ( "make build_libs" , {
124+ cwd : buildCwd
125+ } , { pipeOutput : true } ) ;
126+
127+ await execPromise ( "make test" , {
128+ cwd : buildCwd
129+ } , { pipeOutput : true } ) ;
130+
131+ // only install software, not the docs
132+ await execPromise ( "make install_sw" , {
65133 cwd : buildCwd ,
66134 maxBuffer : 10 * 1024 * 1024 // we should really just use spawn
67135 } , { pipeOutput : true } ) ;
@@ -80,7 +148,7 @@ const buildWin32 = async (buildCwd) => {
80148 } catch {
81149 throw new Error ( `vcvarsall.bat not found at ${ vcvarsallPath } ` ) ;
82150 }
83-
151+
84152 const vcTarget = vcvarsallArch === "x64" ? "VC-WIN64A" : "VC-WIN32" ;
85153 await execPromise ( `"${ win32BatPath } " "${ vcvarsallPath } " ${ vcvarsallArch } ${ vcTarget } ` , {
86154 cwd : buildCwd ,
@@ -128,13 +196,18 @@ const makeOnStreamDownloadProgress = () => {
128196} ;
129197
130198const buildOpenSSLIfNecessary = async ( openSSLVersion , macOsDeploymentTarget ) => {
131- if ( process . platform !== "darwin" && process . platform !== "win32" ) {
199+ if ( process . platform !== "darwin" && process . platform !== "win32" && process . platform !== 'linux' ) {
132200 console . log ( `Skipping OpenSSL build, not required on ${ process . platform } ` ) ;
133201 return ;
134202 }
135203
204+ if ( process . platform === 'linux' && process . env . NODEGIT_OPENSSL_STATIC_LINK !== '1' ) {
205+ console . log ( `Skipping OpenSSL build, NODEGIT_OPENSSL_STATIC_LINK !== 1` ) ;
206+ return ;
207+ }
208+
136209 await removeOpenSSLIfOudated ( openSSLVersion ) ;
137-
210+
138211 try {
139212 await fs . stat ( extractPath ) ;
140213 console . log ( "Skipping OpenSSL build, dir exists" ) ;
@@ -148,7 +221,7 @@ const buildOpenSSLIfNecessary = async (openSSLVersion, macOsDeploymentTarget) =>
148221
149222 const downloadStream = got . stream ( openSSLUrl ) ;
150223 downloadStream . on ( "downloadProgress" , makeOnStreamDownloadProgress ( ) ) ;
151-
224+
152225 await pipeline (
153226 downloadStream ,
154227 new HashVerify ( "sha256" , openSSLSha256 ) ,
@@ -162,6 +235,8 @@ const buildOpenSSLIfNecessary = async (openSSLVersion, macOsDeploymentTarget) =>
162235
163236 if ( process . platform === "darwin" ) {
164237 await buildDarwin ( buildCwd , macOsDeploymentTarget ) ;
238+ } else if ( process . platform === "linux" && process . env . NODEGIT_OPENSSL_STATIC_LINK === '1' ) {
239+ await buildLinux ( buildCwd ) ;
165240 } else if ( process . platform === "win32" ) {
166241 await buildWin32 ( buildCwd ) ;
167242 } else {
@@ -172,11 +247,16 @@ const buildOpenSSLIfNecessary = async (openSSLVersion, macOsDeploymentTarget) =>
172247}
173248
174249const downloadOpenSSLIfNecessary = async ( downloadBinUrl , maybeDownloadSha256 ) => {
175- if ( process . platform !== "darwin" && process . platform !== "win32" ) {
250+ if ( process . platform !== "darwin" && process . platform !== "win32" && process . platform !== 'linux' ) {
176251 console . log ( `Skipping OpenSSL download, not required on ${ process . platform } ` ) ;
177252 return ;
178253 }
179254
255+ if ( process . platform === 'linux' && process . env . NODEGIT_OPENSSL_STATIC_LINK !== '1' ) {
256+ console . log ( `Skipping OpenSSL download, NODEGIT_OPENSSL_STATIC_LINK !== 1` ) ;
257+ return ;
258+ }
259+
180260 try {
181261 await fs . stat ( extractPath ) ;
182262 console . log ( "Skipping OpenSSL download, dir exists" ) ;
@@ -185,7 +265,7 @@ const downloadOpenSSLIfNecessary = async (downloadBinUrl, maybeDownloadSha256) =
185265
186266 const downloadStream = got . stream ( downloadBinUrl ) ;
187267 downloadStream . on ( "downloadProgress" , makeOnStreamDownloadProgress ( ) ) ;
188-
268+
189269 const pipelineSteps = [
190270 downloadStream ,
191271 maybeDownloadSha256 ? new HashVerify ( "sha256" , maybeDownloadSha256 ) : null ,
0 commit comments