Skip to content

Commit

Permalink
feat: support build options via npmrc
Browse files Browse the repository at this point in the history
  • Loading branch information
aminya committed Jun 19, 2024
1 parent ea5f35c commit ab17894
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 54 deletions.
37 changes: 15 additions & 22 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ jobs:
- x64
cpp_arch:
- x64
ARCH:
arch:
- x64
zmq_draft:
- false
docker:
- ""
docker_cmd:
Expand All @@ -35,30 +33,26 @@ jobs:
- os: windows-2022
node_version: 18
node_arch: x86
ARCH: x86
arch: x86
cpp_arch: amd64_x86
zmq_draft: false

# - os: windows-2022
# node_version: 18
# node_arch: x64
# ARCH: arm64
# arch: arm64
# cpp_arch: amd64_arm64
# zmq_draft: false

- os: macos-13
node_version: 18
node_arch: x64
ARCH: x86_64
arch: x86_64
cpp_arch: x64
zmq_draft: false

- os: macos-14
node_version: 18
node_arch: arm64
ARCH: arm64
arch: arm64
cpp_arch: amd64_arm64
zmq_draft: false

# Alpine
- os: ubuntu-22.04
Expand All @@ -69,14 +63,13 @@ jobs:
build.prebuild
node_version: 18
node_arch: x64
ARCH: x64
arch: x64
cpp_arch: x64
zmq_draft: false

env:
ZMQ_DRAFT: ${{ matrix.zmq_draft }}
ZMQ_SHARED: false
ARCH: ${{ matrix.ARCH }}
npm_config_zmq_draft: false
npm_config_zmq_shared: false
npm_config_arch: ${{ matrix.arch }}
steps:
- uses: actions/checkout@v4

Expand All @@ -88,10 +81,10 @@ jobs:
./build/
key:
"cache-OS:${{ matrix.os }}-arch:${{ matrix.node_arch
}}-ZMQ_DRAFT:${{ matrix.zmq_draft }}-Node:${{ matrix.node_version
}}-${{ hashFiles('./package.json') }}"
}}-ZMQ_DRAFT:${{ env.npm_config_zmq_draft }}-Node:${{
matrix.node_version }}-${{ hashFiles('./package.json') }}"
restore-keys: |
"cache-OS:${{ matrix.os }}-arch:${{ matrix.node_arch }}-ZMQ_DRAFT:${{ matrix.zmq_draft }}-Node:${{ matrix.node_version }}-"
"cache-OS:${{ matrix.os }}-arch:${{ matrix.node_arch }}-ZMQ_DRAFT:${{ env.npm_config_zmq_draft }}-Node:${{ matrix.node_version }}-"
- name: Setup Cpp
if: ${{ !matrix.docker }}
Expand All @@ -115,12 +108,12 @@ jobs:
architecture: ${{ matrix.node_arch }}

- name: Install Mac-OS x86_64 Dependencies
if: ${{ contains(matrix.os, 'macos') && matrix.ARCH == 'x86_64' }}
if: ${{ contains(matrix.os, 'macos') && matrix.arch == 'x86_64' }}
run: |
brew install libsodium gnutls
- name: Install Mac-OS arm64 Dependencies
if: ${{ contains(matrix.os, 'macos') && matrix.ARCH == 'arm64' }}
if: ${{ contains(matrix.os, 'macos') && matrix.arch == 'arm64' }}
run: |
brew uninstall libsodium --force --ignore-dependencies
source ./script/macos-arm-deps.sh
Expand Down Expand Up @@ -155,7 +148,7 @@ jobs:
if: "${{ contains(matrix.os, 'ubuntu') && !matrix.docker }}"
run: pnpm run lint-test

- name: Test (Debug)
- name: Test
if: ${{ !matrix.docker }}
uses: nick-fields/retry@v3
with:
Expand Down
72 changes: 61 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,76 @@ source:
- CMake 2.8+
- curl

To install from source:
To install from source, specify `build_from_source=true` in a `.npmrc` file

```sh
npm install zeromq@6.0.0-beta.20 --build-from-source
```
build_from_source=true
```

If you want to link against a shared ZeroMQ library, you can build skip
downloading `libzmq` and link with the installed library instead as follows:
When building from source, you can also specify additional build options in a
`.npmrc` file in your project:

```sh
npm install zeromq@6.0.0-beta.20 --zmq-shared
<details>
<summary>Available Build Options</summary>

#### Draft support

By default `libzmq` is built with support for `Draft` patterns (e.g.
`server-client`, `radio-dish`, `scatter-gather`). If you want to build `libzmq`
without support for `Draft`, you can specify the following in `.npmrc`:

```
zmq_draft=false
```

If you wish to use any DRAFT sockets then it is also necessary to compile the
library from source:
#### Shared library support

```sh
npm install zeromq@6.0.0-beta.20 --zmq-draft
If you want to link against a shared ZeroMQ library installed on your system,
you can build skip downloading `libzmq` and link with the installed library
instead by specifying the following in `.npmrc`:

```ini
zmq_shared=true
```

#### Alternative libzmq version

You can specify an alternative version or Git revision of `libzmq` to build
against by specifying the following in `.npmrc`:

```ini
zmq_version="4.3.5"
```

#### Debug build of libzmq

If you want to build `libzmq` with debug symbols, you can specify the following
in `.npmrc`:

```ini
zmq_build_type="Debug"
```

#### Cross-compilation for different architectures

If you want to cross-compile for a different architecture, you can specify the
following in `.npmrc`:

```ini
arch="arm64"
```

#### MacOS Deployment Target

If you want to specify the MacOS deployment target, you can specify the
following in `.npmrc`:

```ini
macos_deployment_target="10.15"
```

</details>

## Examples

**Note:** These examples assume the reader is familiar with ZeroMQ. If you are
Expand Down
88 changes: 67 additions & 21 deletions script/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,62 @@ import {mkdir, cd, exec, find, mv} from "shelljs"

const root = dirname(__dirname)

type Options = {
zmq_shared: boolean
zmq_version: string
zmq_draft: boolean
zmq_build_type: string
arch: string
macosx_deployment_target?: string
}

function toBool(value: string | undefined): boolean | undefined {
switch (value) {
case "true":
case "1":
return true
case "false":
case "0":
return false
default:
return undefined
}
}

function toString(value: string | undefined): string | undefined {
switch (value) {
case undefined:
case "":
return undefined
default:
return value
}
}

function parseOptions(): Options {
return {
zmq_shared: toBool(process.env.npm_config_zmq_shared) ?? false,
zmq_draft: toBool(process.env.npm_config_zmq_draft) ?? false,
zmq_version:
toString(process.env.npm_config_zmq_version) ??
"5657b4586f24ec433930e8ece02ddba7afcf0fe0",
zmq_build_type:
toString(process.env.npm_config_zmq_build_type) ?? "Release",
arch: toString(process.env.npm_config_arch) ?? process.arch,
macosx_deployment_target:
toString(process.env.npm_config_macosx_deployment_target) ?? "10.15",
}
}

function main() {
const zmq_rev =
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing, @typescript-eslint/strict-boolean-expressions
process.env.ZMQ_VERSION || "5657b4586f24ec433930e8ece02ddba7afcf0fe0"
const src_url = `https://github.com/zeromq/libzmq/archive/${zmq_rev}.tar.gz`
const opts = parseOptions()
console.log("Building libzmq with options ", opts)

if (opts.zmq_shared) {
return
}

const src_url = `https://github.com/zeromq/libzmq/archive/${opts.zmq_version}.tar.gz`

const libzmq_build_prefix = `${root}/build/libzmq-staging`
const libzmq_install_prefix = `${root}/build/libzmq`
Expand All @@ -17,29 +68,25 @@ function main() {
process.platform === "win32" ? ".lib" : ".a"
}`

const src_dir = `libzmq-${zmq_rev}`
const tarball = `libzmq-${zmq_rev}.tar.gz`

// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing, @typescript-eslint/strict-boolean-expressions
const CMAKE_BUILD_TYPE = process.env.CMAKE_BUILD_TYPE || "Release"
const src_dir = `libzmq-${opts.zmq_version}`
const tarball = `libzmq-${opts.zmq_version}.tar.gz`

let build_options: string = ""

// https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
if (process.platform === "win32") {
if (CMAKE_BUILD_TYPE !== "Debug") {
if (opts.zmq_build_type !== "Debug") {
build_options += " -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL"
} else {
build_options += " -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL"
}
}

build_options += archCMakeOptions()
build_options += archCMakeOptions(opts)

if (process.platform === "darwin") {
const MACOSX_DEPLOYMENT_TARGET = "10.15"
process.env.MACOSX_DEPLOYMENT_TARGET = MACOSX_DEPLOYMENT_TARGET
build_options += ` -DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}`
process.env.MACOSX_DEPLOYMENT_TARGET = opts.macosx_deployment_target
build_options += ` -DCMAKE_OSX_DEPLOYMENT_TARGET=${opts.macosx_deployment_target}`
}

mkdir("-p", libzmq_build_prefix)
Expand All @@ -65,24 +112,24 @@ function main() {
exec(`tar xzf "${tarball}"`, execOptions)
}

if (process.env.ZMQ_DRAFT === "true") {
if (opts.zmq_draft) {
console.log("Enabling draft support")
build_options += " -DENABLE_DRAFTS=ON"
}

console.log(`Building libzmq ${CMAKE_BUILD_TYPE}`)
console.log(`Building libzmq ${opts.zmq_build_type}`)

// ClangFormat include causes issues but is not required to build.
const clang_format_file = `${src_dir}/builds/cmake/Modules/ClangFormat.cmake`
if (existsSync(clang_format_file)) {
writeFileSync(clang_format_file, "")
}

const cmake_configure = `cmake -S "${src_dir}" -B ./build ${build_options} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX="${libzmq_install_prefix}" -DCMAKE_INSTALL_LIBDIR=lib -DBUILD_STATIC=ON -DBUILD_TESTS=OFF -DBUILD_SHARED=OFF -DWITH_DOCS=OFF -DWITH_LIBSODIUM=OFF`
const cmake_configure = `cmake -S "${src_dir}" -B ./build ${build_options} -DCMAKE_BUILD_TYPE=${opts.zmq_build_type} -DCMAKE_INSTALL_PREFIX="${libzmq_install_prefix}" -DCMAKE_INSTALL_LIBDIR=lib -DBUILD_STATIC=ON -DBUILD_TESTS=OFF -DBUILD_SHARED=OFF -DWITH_DOCS=OFF -DWITH_LIBSODIUM=OFF`
console.log(cmake_configure)
exec(cmake_configure, execOptions)

const cmake_build = `cmake --build ./build --config ${CMAKE_BUILD_TYPE} --target install --parallel`
const cmake_build = `cmake --build ./build --config ${opts.zmq_build_type} --target install --parallel`
console.log(cmake_build)
exec(cmake_build, execOptions)

Expand All @@ -95,9 +142,8 @@ function main() {

main()

function archCMakeOptions() {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing, @typescript-eslint/strict-boolean-expressions
const arch = (process.env.ARCH || process.arch).toLowerCase()
function archCMakeOptions(opts: Options) {
const arch = opts.arch.toLowerCase()

if (process.platform === "win32") {
// CMAKE_GENERATOR_PLATFORM only supported on Windows
Expand Down

0 comments on commit ab17894

Please sign in to comment.