Skip to content

Commit

Permalink
build: update clang-fetcher with libcxx headers and object paths
Browse files Browse the repository at this point in the history
  • Loading branch information
VerteDinde committed May 25, 2021
1 parent c35888a commit ea37945
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/clang-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as zlib from 'zlib';
import { ELECTRON_GYP_DIR } from './constants';
import { fetch } from './fetcher';
import { downloadLinuxSysroot } from './sysroot-fetcher';
import { downloadLibcxxHeaders, downloadLibcxxObjects } from './libcxx-fetcher';

const d = debug('electron-rebuild');

Expand Down Expand Up @@ -50,6 +51,46 @@ export async function getClangEnvironmentVars(electronVersion: string, targetArc
if (process.platform === 'linux') {
const sysrootPath = await downloadLinuxSysroot(electronVersion, targetArch);
clangArgs.push('--sysroot', sysrootPath);

const cc = `"${path.resolve(clangDir, 'clang')}" ${clangArgs.join(' ')}`
const cxx = `"${path.resolve(clangDir, 'clang++')}" ${clangArgs.join(' ')}`

// on Electron 13 or higher, build native modules with Electron's libc++ libraries
if (parseInt(electronVersion.split('.')[0]) >= 13) {
const libcxxObjectsDownloadDir = await downloadLibcxxObjects(electronVersion, targetArch)
const libcxxHeadersDownloadDir = await downloadLibcxxHeaders(electronVersion, ['libc++', 'libc++abi'])

const libcxxObjects = path.resolve(libcxxObjectsDownloadDir, 'libc++')
const libcxxHeaders = path.resolve(libcxxHeadersDownloadDir, 'libc++')
const libcxxabiHeaders = path.resolve(libcxxHeadersDownloadDir, 'libc++abi')

const cxxflags = [
'-std=c++14',
'-nostdinc++',
'-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS',
`-isystem"${libcxxHeaders}"`,
`-isystem"${libcxxabiHeaders}"`,
'-fPIC'
].join(' ');

const ldflags = [
'-stdlib=libc++',
'-fuse-ld=lld',
`-L"${libcxxObjects}"`,
'-lc++abi'
].join(' ');

return {
env: {
CC: cc,
CXX: cxx,
CFLAGS: cxxflags,
CXXFLAGS: cxxflags,
LDFLAGS: ldflags,
},
args: gypArgs,
}
}
}

return {
Expand Down
71 changes: 71 additions & 0 deletions src/libcxx-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as debug from 'debug';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as tar from 'tar';
import * as zlib from 'zlib';
import { ELECTRON_GYP_DIR } from './constants';
import { fetch } from './fetcher';

const d = debug('electron-rebuild');

// Determine base where we download these headers
// `-isystem"${path.resolve(BASE, 'buildtools', 'third_party', 'libc++', 'trunk', 'include')}"`,
// `-isystem"${path.resolve(BASE, 'buildtools', 'third_party', 'libc++abi', 'trunk', 'include')}"`,
export async function downloadLibcxxHeaders(electronVersion: string, libs: string[]): Promise<string> {
const headersDirPath = path.resolve(ELECTRON_GYP_DIR, `${electronVersion}-libcxx_headers`);

for (const lib_name in libs) {
if (await fs.pathExists(path.resolve(headersDirPath, `${lib_name}`))) return headersDirPath;
if (!await fs.pathExists(ELECTRON_GYP_DIR)) await fs.mkdirp(ELECTRON_GYP_DIR);

// download libcxxabi_headers.zip
const contents = await fetch(`https://raw.githubusercontent.com/electron/electron/v${electronVersion}/${lib_name}_headers.zip`, 'buffer')
d(`deflating ${lib_name}_headers`);
zlib.deflateSync(contents);
const tarPath = path.resolve(ELECTRON_GYP_DIR, `${electronVersion}-${lib_name}_headers.tar`);
if (await fs.pathExists(tarPath)) await fs.remove(tarPath)
await fs.writeFile(tarPath, Buffer.from(contents));
await fs.mkdirp(headersDirPath);

d(`tar running on ${lib_name}_headers`);
await tar.x({
file: tarPath,
cwd: headersDirPath,
});

await fs.remove(tarPath);
d(`cleaning up ${lib_name}_headers tar file`);
}
return headersDirPath;
}

// Determine base where we download these headers
// `-L"${path.resolve(BASE, 'out', `${utils.getOutDir({ shouldLog: true })}`, 'obj', 'buildtools', 'third_party', 'libc++abi')}"`,
// `-L"${path.resolve(BASE, 'out', `${utils.getOutDir({ shouldLog: true })}`, 'obj', 'buildtools', 'third_party', 'libc++')}"`,
export async function downloadLibcxxObjects(electronVersion: string, targetArch: string): Promise<string> {
const platform = process.platform;
const libcxxObjectsDirPath = path.resolve(ELECTRON_GYP_DIR, 'libcxx-objects');

if (await fs.pathExists(path.resolve(libcxxObjectsDirPath, 'libcxx-objects'))) return libcxxObjectsDirPath;
if (!await fs.pathExists(ELECTRON_GYP_DIR)) await fs.mkdirp(ELECTRON_GYP_DIR);

// download objects (e.g. libcxx-objects-v13.0.0-linux-x64.zip)
const contents = await fetch(`https://raw.githubusercontent.com/electron/electron/v${electronVersion}/libcxx-objects-v${electronVersion}-${platform}-${targetArch}.zip`, 'buffer')
d(`deflating libcxx-objects-${platform}-${targetArch}`);
zlib.deflateSync(contents);
const tarPath = path.resolve(ELECTRON_GYP_DIR, `libcxx-objects-v${electronVersion}-${platform}-${targetArch}.tar`);
if (await fs.pathExists(tarPath)) await fs.remove(tarPath)
await fs.writeFile(tarPath, Buffer.from(contents));
await fs.mkdirp(libcxxObjectsDirPath);

d(`tar running on libcxx-objects-${platform}-${targetArch}`);
await tar.x({
file: tarPath,
cwd: libcxxObjectsDirPath,
});

await fs.remove(tarPath);
d(`cleaning up libcxx-objects-${platform}-${targetArch} tar file`);
return libcxxObjectsDirPath;
}

0 comments on commit ea37945

Please sign in to comment.