diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 08fda6b4..c2a29fd1 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -15,7 +15,7 @@ jobs: build: name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.os }} - timeout-minutes: 60 + timeout-minutes: 120 permissions: contents: read strategy: @@ -25,8 +25,6 @@ jobs: - { name: "Windows GCC", os: windows-latest, - builddir: "Make/gccWin", - makefile: "Makefile.gccWin", release_name: "win-x86_64-gcc", release_extension: ".zip", archive_command: "7z a -tzip -mmt" @@ -34,26 +32,134 @@ jobs: - { name: "Ubuntu GCC", os: ubuntu-latest, - builddir: "Make/gcc", - makefile: "Makefile", release_name: "linux-x86_64-gcc", release_extension: ".tar.xz", archive_command: "tar cvfJ" } + - { + name: "Ubuntu MinGW Cross-Compile", + os: ubuntu-latest, + cc: "x86_64-w64-mingw32-gcc", + cxx: "x86_64-w64-mingw32-g++", + ar: "x86_64-w64-mingw32-ar", + mingw_cross: true, + release_name: "win-x86_64-ubuntu-mingw", + release_extension: ".zip", + archive_command: "zip -r" + } + - { + name: "MSYS2 MINGW64 GCC", + os: windows-latest, + msys2_msystem: "MINGW64", + release_name: "win-x86_64-msys2-mingw64", + release_extension: ".zip", + archive_command: "7z a -tzip -mmt" + } + - { + name: "MSYS2 UCRT64 GCC", + os: windows-latest, + msys2_msystem: "UCRT64", + release_name: "win-x86_64-msys2-ucrt64", + release_extension: ".zip", + archive_command: "7z a -tzip -mmt" + } + # VMActions builds for BSD and Solaris platforms + - { + name: "VMActions FreeBSD latest (x86_64) Make Build", + os: ubuntu-latest, + vm_actions: true, + vm_platform: "freebsd", + vm_release: "", + vm_arch: "x86_64", + release_name: "freebsd-x86_64-make", + release_extension: ".tar.xz", + archive_command: "tar cvfJ" + } + - { + name: "VMActions OpenBSD latest (x86_64) Make Build", + os: ubuntu-latest, + vm_actions: true, + vm_platform: "openbsd", + vm_release: "", + vm_arch: "x86_64", + release_name: "openbsd-x86_64-make", + release_extension: ".tar.xz", + archive_command: "tar cvfJ" + } + - { + name: "VMActions NetBSD latest (x86_64) Make Build", + os: ubuntu-latest, + vm_actions: true, + vm_platform: "netbsd", + vm_release: "", + vm_arch: "x86_64", + release_name: "netbsd-x86_64-make", + release_extension: ".tar.xz", + archive_command: "tar cvfJ" + } + - { + name: "VMActions DragonFlyBSD latest (x86_64) Make Build", + os: ubuntu-latest, + vm_actions: true, + vm_platform: "dragonflybsd", + vm_release: "", + vm_arch: "x86_64", + release_name: "dragonflybsd-x86_64-make", + release_extension: ".tar.xz", + archive_command: "tar cvfJ" + } + - { + name: "VMActions OmniOS r151054 (x86_64) Make Build", + os: ubuntu-latest, + vm_actions: true, + vm_platform: "omnios", + vm_release: "r151054", + vm_arch: "x86_64", + release_name: "omnios_r151054-x86_64-make", + release_extension: ".tar.xz", + archive_command: "tar cvfJ" + } + - { + name: "VMActions Solaris 11.4 (x86_64) Make Build", + os: ubuntu-latest, + cc: "gcc", + cxx: "g++", + vm_actions: true, + vm_platform: "solaris", + vm_release: "11.4-gcc", + vm_arch: "x86_64", + release_name: "solaris_11_4-x86_64-make", + release_extension: ".tar.xz", + archive_command: "tar cvfJ" + } defaults: run: shell: bash steps: - - name: Harden Runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.1 - with: - egress-policy: audit + # No runner hardening since it breaks the VMActions even though there is an ifcondition here + # - name: Harden Runner + # if: matrix.config.vm_actions != true + # uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.14.1 + # with: + # egress-policy: audit - uses: actions/checkout@v6.0.2 with: submodules: recursive + - name: Setup MSYS2 + if: matrix.config.msys2_msystem != '' + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.config.msys2_msystem }} + update: true + install: >- + base-devel + git + pacboy: >- + toolchain:p + - name: Escape backslash in branch name run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | tr / -)" >> $GITHUB_ENV @@ -67,30 +173,180 @@ jobs: run: | echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH + - name: Install MinGW cross-compiler + if: matrix.config.mingw_cross == true + run: | + sudo apt-get update + sudo apt-get install -y mingw-w64 zip + - name: Make buildjsonc.sh executable + if: matrix.config.vm_actions != true && matrix.config.msys2_msystem == '' run: chmod +x Make/buildjsonc.sh + # Ubuntu MinGW cross-compile build + - name: make (MinGW cross-compile) + if: matrix.config.mingw_cross == true + env: + CC: ${{ matrix.config.cc }} + CXX: ${{ matrix.config.cxx }} + AR: ${{ matrix.config.ar }} + run: | + make BUILD_TYPE=release + + # Traditional make builds (Windows/Ubuntu native) - name: make - working-directory: ${{ matrix.config.builddir }} + if: matrix.config.vm_actions != true && matrix.config.msys2_msystem == '' && matrix.config.mingw_cross != true + run: | + make BUILD_TYPE=release + + # MSYS2 make builds (MINGW64/UCRT64) + - name: make (MSYS2) + if: matrix.config.msys2_msystem != '' + shell: msys2 {0} run: | - make release -f ${{ matrix.config.makefile }} + chmod +x Make/buildjsonc.sh + make BUILD_TYPE=release + + # VMActions FreeBSD Build + - name: Build with Make (VMActions FreeBSD) + if: matrix.config.vm_actions == true && matrix.config.vm_platform == 'freebsd' + uses: vmactions/freebsd-vm@v1 + with: + envs: 'DESTDIR' + release: ${{ matrix.config.vm_release }} + arch: ${{ matrix.config.vm_arch }} + usesh: true + prepare: | + pkg update || true + pkg install -y curl gmake bash + pkg install -y ntp + ntpdate -u pool.ntp.org + + run: | + chmod +x Make/buildjsonc.sh + gmake BUILD_TYPE=release + + # VMActions OpenBSD Build + - name: Build with Make (VMActions OpenBSD) + if: matrix.config.vm_actions == true && matrix.config.vm_platform == 'openbsd' + uses: vmactions/openbsd-vm@v1 + with: + envs: 'DESTDIR' + release: ${{ matrix.config.vm_release }} + arch: ${{ matrix.config.vm_arch }} + usesh: true + prepare: | + pkg_add curl gmake bash + + # force a sync in the VM + ntpctl -s status || true + + run: | + chmod +x Make/buildjsonc.sh + gmake BUILD_TYPE=release + + # VMActions NetBSD Build + - name: Build with Make (VMActions NetBSD) + if: matrix.config.vm_actions == true && matrix.config.vm_platform == 'netbsd' + uses: vmactions/netbsd-vm@v1 + with: + envs: 'DESTDIR' + release: ${{ matrix.config.vm_release }} + arch: ${{ matrix.config.vm_arch }} + usesh: true + prepare: | + /usr/sbin/pkg_add curl gmake + /usr/sbin/pkg_add ntp + + run: | + chmod +x Make/buildjsonc.sh + gmake BUILD_TYPE=release + + # VMActions DragonFlyBSD Build + - name: Build with Make (VMActions DragonFlyBSD) + if: matrix.config.vm_actions == true && matrix.config.vm_platform == 'dragonflybsd' + uses: vmactions/dragonflybsd-vm@v1 + with: + envs: 'DESTDIR' + release: ${{ matrix.config.vm_release }} + arch: ${{ matrix.config.vm_arch }} + usesh: true + prepare: | + pkg update || true + pkg install -y curl gmake bash gcc + /usr/sbin/dntpd -s + + run: | + chmod +x Make/buildjsonc.sh + gmake BUILD_TYPE=release + + # VMActions OmniOS Build + - name: Build with Make (VMActions OmniOS) + if: matrix.config.vm_actions == true && matrix.config.vm_platform == 'omnios' + uses: vmactions/omnios-vm@v1 + with: + envs: 'DESTDIR' + release: ${{ matrix.config.vm_release }} + arch: ${{ matrix.config.vm_arch }} + usesh: true + prepare: | + pkg install pkg:/package/pkg || true + pkg update || true + pkg install socat + + run: | + pkg install build-essential pkg-config + + chmod +x Make/buildjsonc.sh + gmake BUILD_TYPE=release + + # VMActions Solaris Build + - name: Build with Make (VMActions Solaris) + if: matrix.config.vm_actions == true && matrix.config.vm_platform == 'solaris' + uses: vmactions/solaris-vm@v1 + env: + CC: ${{ matrix.config.cc }} + CXX: ${{ matrix.config.cxx }} + with: + envs: 'DESTDIR CC CXX' + release: ${{ matrix.config.vm_release }} + arch: ${{ matrix.config.vm_arch }} + usesh: true + prepare: | + pkg update --accept || true + pkg install --accept developer/build/gnu-make || true + pkgutil -y -i socat + + ntpdate -u pool.ntp.org + + run: | + chmod +x Make/buildjsonc.sh + gmake BUILD_TYPE=release - name: Packing release env: ARCHIVE_EXT: ${{ matrix.config.release_extension }} run: | - mkdir build + # Find the bin directory and copy to DESTDIR for packaging + BIN_DIR=$(find build -type d -name bin | head -n 1) + if [ -z "$BIN_DIR" ]; then + echo "Error: No bin directory found in build/" + exit 1 + fi + echo "Found executables in: $BIN_DIR" + + # Copy binaries to a clean directory for packaging (matches meson approach) + mkdir -p "build/${DESTDIR}" + cp -r "${BIN_DIR}"/* "build/${DESTDIR}/" + + # Create archive from build directory (simpler, matches meson.yml) cd build - ${{ matrix.config.archive_command }} "${DESTDIR}${ARCHIVE_EXT}" ../${{ matrix.config.builddir }}/openseachest_exes + ${{ matrix.config.archive_command }} "${DESTDIR}${ARCHIVE_EXT}" "${DESTDIR}" - - name: Uploading artifacts - uses: actions/upload-artifact@v6.0.0 + - name: Upload Artifact + uses: actions/upload-artifact@v4 with: - name: ${{ format('{0}', env.DESTDIR) }} - path: ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} + name: ${{ env.DESTDIR }} + path: ./build/${{ env.DESTDIR }}${{ matrix.config.release_extension }} - # - name: Publish release - # if: ${{ startsWith(github.ref, 'refs/tags/v') && matrix.config.publish_release }} - # uses: softprops/action-gh-release@v2 - # with: - # files: ${{ format('./build/{0}{1}', env.DESTDIR, matrix.config.release_extension) }} + # Not publishing release from make since this comes from meson instead. This CI is meant to check that we preserve compatibility with older make systems as a backup only. diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml index 17b13de9..b153a5eb 100644 --- a/.github/workflows/meson.yml +++ b/.github/workflows/meson.yml @@ -253,22 +253,19 @@ jobs: vm_release: "r151054", vm_arch: "x86_64", } - # Disabled due to being extremely slow to install required packages for builds. - # Will revisit in future versions of this action to see if it improves. Not sure if this is a - # action issue or an OpenIndiana package repo issue. - # - { - # name: "VMActions OpenIndiana Build (x86_64)", - # os: ubuntu-latest, - # cc: "", - # cxx: "", - # publish_release: true, - # release_name: "openindiana-x86_64", - # release_extension: ".tar.xz", - # archive_command: "tar cvfJ", - # vm_actions: true, - # vm_release: "", - # vm_arch: "x86_64", - # } + - { + name: "VMActions OpenIndiana Build (x86_64)", + os: ubuntu-latest, + cc: "", + cxx: "", + publish_release: true, + release_name: "openindiana-x86_64", + release_extension: ".tar.xz", + archive_command: "tar cvfJ", + vm_actions: true, + vm_release: "202510-build", + vm_arch: "x86_64", + } - { name: "VMActions Solaris Build (x86_64)", os: ubuntu-latest, @@ -699,10 +696,8 @@ jobs: pkg install pkg:/package/pkg || true pkg update || true pkg install socat - - run: | pkg install build-essential ninja pkg-config - + run: | python3 -m pip install --upgrade pip setuptools wheel --root-user-action=ignore python3 -m pip install meson --root-user-action=ignore meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release @@ -720,10 +715,9 @@ jobs: pkg install pkg:/package/pkg || true pkg update || true pkg install socat - + pkg install ninja pkg-config + pkg install library/python/pip || true run: | - pkg install build-essential ninja pkg-config - python3 -m pip install --upgrade pip setuptools wheel --root-user-action=ignore python3 -m pip install meson --root-user-action=ignore meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release @@ -740,12 +734,9 @@ jobs: prepare: | pkg update --accept || true pkgutil -y -i socat - ntpdate -u pool.ntp.org - - run: | pkg install --accept developer/build/meson - + run: | meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release meson install -C build @@ -762,10 +753,8 @@ jobs: pkg install -y curl pkg install -y ntp ntpdate -u pool.ntp.org - - run: | pkg install -y meson - + run: | meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release meson install -C build @@ -781,10 +770,9 @@ jobs: pkg update || true pkg install -y socat /usr/sbin/dntpd -s - - run: | pkg install -y meson + run: | meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release meson install -C build @@ -802,10 +790,8 @@ jobs: # force a sync in the VM ntpctl -s status || true - - run: | pkg_add meson - + run: | meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release meson install -C build @@ -823,15 +809,11 @@ jobs: # Removed for now because this crashes from errors in a config file for unknown reasons. # /usr/pkg/sbin/ntpd -gq - - run: | /usr/sbin/pkg_add meson - + run: | meson setup build -Dprefix=/ -Dmandir=/man -Dbindir=/ ${{ matrix.config.meson_opts }} --buildtype=release meson install -C build - - - name: Install Go for nfpm if: ${{ matrix.config.create_package }} uses: actions/setup-go@v6 diff --git a/.gitignore b/.gitignore index d3c478b4..5a3ee92a 100644 --- a/.gitignore +++ b/.gitignore @@ -370,3 +370,7 @@ dkms.conf # Meson build dir /builddir + +# Meson build artifacts +**/.wraplock +**/meson-private/ diff --git a/BUILDING.md b/BUILDING.md index ac486e1a..136b920a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -88,27 +88,381 @@ This is a brief list of the known features used from C99 that a compiler should ## Building -Run the following commands: +openSeaChest supports two build systems: - meson --buildtype=release builddir +1. **Meson** (recommended) - Modern, cross-platform, well-documented +2. **GNU Make** - Maintained for backwards compatibility and platforms where Meson is unavailable + +**We recommend using Meson** for new builds. The GNU Make build system is provided for: +- Platforms where Meson is not available or not working +- Backwards compatibility with existing build workflows +- Environments where installing Python (required for Meson) is not feasible +- Supporting platforms the meson does not currently support (ex: AIX, HP-UX) + +### Building with Meson (Recommended) + +Meson is a modern build system with excellent cross-platform support and comprehensive documentation. + +**Quick Start:** + + # Basic build + meson setup --buildtype=release builddir ninja -C builddir -The tools will be in the builddir. -To install them system-wide, simply run `ninja -C builddir install` with appropriate permissions + # Parallel build (faster) + ninja -C builddir -j$(nproc) -To cross-compile, see [the official docs](https://mesonbuild.com/Cross-compilation.html) + # Install system-wide + sudo ninja -C builddir install -To build with a different compiler, set the CC environment variable to your desired compiler. -Example: +The tools will be in `builddir/` after building. - CC=clang meson --buildtype=release buildclang - ninja -C buildclang +**Build Types:** -NOTE: If using GCC and older than [5.5.0](https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Standards.html#Standards), the C standard defaults to gnu90. Add the flag `-Dc_std=gnu99` to build openSeaChest. This is needed for CentOS 7 which uses GCC [4.8.5](https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Standards.html#Standards) -Example: + meson setup --buildtype=release builddir # Optimized (-O2, default) + meson setup --buildtype=debug builddir # Debug (-O0 -g) + meson setup --buildtype=debugoptimized builddir # Debug + optimization (-O2 -g) + meson setup --buildtype=minsize builddir # Minimize size (-Os) + +**Build Options:** + + # Enable JSON support + meson setup -Denable_json=true builddir + + # Use different compiler + CC=clang CXX=clang++ meson setup builddir + + # Custom installation prefix + meson setup --prefix=/usr builddir + + # Old GCC (< 5.5.0) requiring C99 + meson setup -Dc_std=gnu99 builddir + +**Cross-Compilation:** + +We provide **38 pre-configured cross-compilation files** in `meson_crosscompile/` for various architectures: + +*MUSL-based cross-compilers (portable, static):* +- ARM: `aarch64`, `armv5l`, `armv6`, `armv7l`, `armv7r` +- x86: `i486`, `i686`, `x86_64` +- MIPS: `mips`, `mips64`, `mipsel`, `mips64el` +- PowerPC: `powerpc`, `powerpc64`, `powerpc64le` +- Others: `riscv64`, `s390x` + +*Ubuntu-based cross-compilers:* +- Various architectures: `aarch64`, `armhf`, `ppc`, `ppc64le`, `riscv64`, `s390x`, `sparc64`, etc. + +*Windows:* +- `Windows-Clang.txt` - Clang on Windows +- `msvc_arm64.txt` - MSVC ARM64 + +**Example cross-compilation:** + + # Using MUSL cross-compiler for ARM + meson setup --cross-file meson_crosscompile/aarch64-linux-musl-cross.txt buildarm + + # Using Ubuntu cross-compiler + meson setup --cross-file meson_crosscompile/ubuntu_ppc64le.txt buildppc + +**Alternative: muon and samurai (Python-free)** + +For environments where Python is unavailable, you can use [muon](https://sr.ht/~lattis/muon/) and [samurai](https://github.com/michaelforney/samurai) as drop-in replacements for Meson and Ninja: + + muon setup builddir + samu -C builddir + +These tools aim to be compatible with Meson/Ninja but are written in C and have no Python dependency. openSeaChest should be compatible with muon and samurai, although we have only done limited testing to confirm successful builds. For installation instructions and full documentation, see the respective project pages. + +**Tips and Troubleshooting:** + +*Faster Builds:* + + ninja -C builddir -j$(nproc) # Use all CPU cores + +*Optimization Flags:* + + # Maximum optimization (may increase size) + meson setup -Dc_args='-O3 -march=native' builddir + + # Link-time optimization + meson setup -Db_lto=true builddir + +*Debugging:* + + # Verbose build output + ninja -C builddir -v + + # Introspect configuration + meson introspect builddir --buildoptions + meson configure builddir + +*Reconfigure existing build:* + + meson configure builddir --buildtype=debug + ninja -C builddir + +*Common Issues:* +- Meson requires Python 3.6+ - install with `pip3 install meson ninja` +- For detailed cross-compilation docs, see: https://mesonbuild.com/Cross-compilation.html +- For all Meson options and features, see: https://mesonbuild.com/ + +### Building with GNU Make + +The GNU Make build system is maintained for backwards compatibility and platforms where Meson is unavailable. + +**Note:** We recommend using Meson for new builds. Use Make only when: +- Meson is not available on your platform +- You cannot install Python (required for Meson) +- You have existing Make-based workflows + +**Requirements:** +* GNU Make 3.81 or later +* GCC 4.7+ or Clang 3.0+ +* For JSON support (optional): CMake and json-c library + +**Quick Start:** + + # Basic build (auto-detects platform, builds release) + make + + # Parallel build using all CPU cores + make -j$(nproc) + + # Install to system (default: /usr/local) + sudo make install + + # Create distribution tarball + make package + +**Build Configuration:** + + # Build types + make BUILD_TYPE=debug # Debug build (-g -O0) + make BUILD_TYPE=release # Release build (-O2, default) + make BUILD_TYPE=static-debug # Static debug build + make BUILD_TYPE=static-release # Static release build + + # Optional features + make BUILD_JSON=1 # Enable JSON output support + make BUILD_SHARED_LIBS=1 # Build shared libraries (.so) + + # Platform override (for cross-compilation) + make PLATFORM=windows CC=x86_64-w64-mingw32-gcc + make PLATFORM=freebsd + + # Custom installation prefix + make install PREFIX=/opt/seagate + +**Available Targets:** + + make all # Build all libraries and tools (default) + make libraries # Build only opensea-* libraries + make tools # Build only openSeaChest utilities + make check / test # Run basic smoke tests + make clean # Clean current build type + make clean-all # Clean all build types + make mostlyclean # Clean objects and tools (keep libraries) + make distclean # Remove all generated files including packages + make install # Install binaries, libraries, headers + make install-strip # Install with debug symbols stripped + make installdirs # Create installation directories only + make uninstall # Remove installed files + make package # Create tar.gz distribution + make show-config # Display build configuration + make print-tools # List all tools to build + make print-libs # List all libraries to build + make help # Show all available targets + +**Build Type Shortcuts:** + + make release # Optimized build (-O3, default) + make debug # Debug build (-O0 -g3) + make relwithdebinfo # Optimized with debug symbols (-O2 -g) + make minsize # Minimize binary size (-Os) + make static-release # Static release build + make static-debug # Static debug build + +**Individual Library Targets:** + + make opensea-common # Build opensea-common library only + make opensea-transport # Build opensea-transport library only + make opensea-operations # Build opensea-operations library only + make opensea-jsonformat # Build opensea-jsonformat (if BUILD_JSON=1) + +**Individual Tool Targets:** + +All 18 openSeaChest utilities can be built individually: + + make openSeaChest_Basics + make openSeaChest_Configure + make openSeaChest_Defect + make openSeaChest_Erase + make openSeaChest_Firmware + make openSeaChest_Format + make openSeaChest_GenericTests + make openSeaChest_Info + make openSeaChest_Logs + make openSeaChest_NVMe + make openSeaChest_PassthroughTest + make openSeaChest_PowerControl + make openSeaChest_Raw + make openSeaChest_Reservations + make openSeaChest_Security + make openSeaChest_SMART + make openSeaChest_ZBD + +**Supported Platforms:** +* Linux (all architectures) +* Windows (MinGW/MSYS2) +* FreeBSD, OpenBSD, NetBSD, DragonFlyBSD +* Solaris, Illumos +* AIX +* VMware ESXi (requires VMware DDK) + +**Build System Features:** +* Automatic dependency tracking (`.d` files) +* Parallel build support (`make -j`) +* Cross-platform support with automatic detection +* OpenSSF security hardening (stack protection, RELRO, NX, PIE) +* Compiler warning flags from Meson build (50+ warnings) +* Platform-specific optimizations + +**Directory Structure:** + +Build outputs are organized by platform and configuration: + + build/ + └── linux-x86_64-release/ + ├── bin/ # openSeaChest utilities + ├── lib/ # Static/shared libraries + └── obj/ # Object files and .d dependencies + ├── common/ + ├── transport/ + ├── operations/ + └── tools/ + +**Examples:** + + # Development build with verbose output + make BUILD_TYPE=debug V=1 + + # Optimized static build + make BUILD_TYPE=static-release -j$(nproc) + + # Build with JSON support and install to /usr + make BUILD_JSON=1 PREFIX=/usr install + + # Cross-compile for Windows from Linux + make PLATFORM=windows CC=x86_64-w64-mingw32-gcc + + # Package for distribution + make BUILD_TYPE=static-release package + # Creates: openSeaChest---.tar.gz + +**Tips and Troubleshooting:** + +**Faster Builds:** + +Use parallel compilation to significantly reduce build time: + + # Use all CPU cores + make -j$(nproc) + + # Use specific number of cores + make -j8 + +**Debugging Build Failures:** + +Enable verbose output to see full compiler commands: + + make V=1 # See all compiler commands + make V=1 BUILD_TYPE=debug # Verbose debug build + +Check build configuration: + + make show-config # Display current settings + make print-tools # List tools to build + make print-libs # List libraries to build + +**Cross-Compilation:** + +When cross-compiling, explicitly set compiler and platform: + + # MinGW cross-compile from Linux + make PLATFORM=windows \ + CC=x86_64-w64-mingw32-gcc \ + CXX=x86_64-w64-mingw32-g++ \ + AR=x86_64-w64-mingw32-ar + + # Install MinGW toolchain on Ubuntu/Debian: + sudo apt-get install mingw-w64 + +**Platform-Specific Notes:** + +*Solaris/OmniOS:* Explicitly set compiler if needed: + + # Use GCC on Solaris + make CC=gcc CXX=g++ + + # Some linker flags may not be supported + # The build system tests flags automatically + +*BSD Systems:* Default compiler is usually Clang: + + # FreeBSD/OpenBSD/NetBSD auto-detect Clang + make + + # Force GCC if installed + make CC=gcc CXX=g++ + +*Windows (MinGW/MSYS2):* Use the appropriate shell: + + # From MSYS2 MinGW64 shell + make + + # From MSYS2 UCRT64 shell + make + +**Common Issues:** + +1. **Compiler Warnings (Make vs Meson):** + - Some warnings may appear in Make builds but not Meson builds (or vice versa) + - This is typically due to differences in how compilers are invoked + - Example: `safe_strlen()` may warn about string overread checks in Make builds, but not in meson, however this is guarded within the C code properly and may not be detected by the compiler properly in some situations. + - These are usually false positives - the code is safely handled + - If Meson builds without warnings but Make shows them, it's likely not a real issue + - The code is tested with both build systems and compiler warning configurations + - If you do find an error or bug, or can contribute a way to fix these warnings, please open a pull request! + +2. **Case-Sensitive Headers (MinGW cross-compile):** + - Windows headers in MinGW are lowercase (e.g., `windows.h`, `basetsd.h`) + - Fixed in codebase but useful to know if adding new Windows code + +3. **Missing Compiler:** + - Install build tools: `apt install build-essential` (Debian/Ubuntu) + - Install gcc/clang: `pkg install gcc` (Solaris/BSD) + +3. **Linker Errors:** + - The build system automatically tests linker flags + - Unsupported flags are skipped on incompatible platforms + +4. **Submodule Issues:** + - Ensure submodules are initialized: `git submodule update --init --recursive` + +5. **Stale Build:** + - Clean and rebuild: `make clean-all && make` + +**Performance Tuning:** + + # Minimal size (embedded systems) + make BUILD_TYPE=minsize + + # Maximum optimization (may increase size) + make CFLAGS="-O3 -march=native" + + # Link-time optimization (LTO) with auto-parallelization + make CFLAGS="-flto=auto" LDFLAGS="-flto=auto" - meson --buildtype=release -Dc_std=gnu99 buildOldGCC - ninja -C buildOldGCC ## Documentation diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 00000000..b68d8a6c --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2012-2025 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file GNUmakefile (root convenience wrapper) +# \brief Forwards all targets to Make/GNUmakefile +# +# USAGE: +# make [target] [VARIABLES] +# +# This wrapper allows running `make` from the project root without needing to +# specify the Make/ directory. All targets and variables are forwarded to the +# actual build system in Make/GNUmakefile. + +# Forward all targets to Make/GNUmakefile +%: + @$(MAKE) -C Make $(MAKECMDGOALS) + +# Special handling for no target (default) +.DEFAULT_GOAL := all + +all: + @$(MAKE) -C Make all + +# Ensure this Makefile doesn't interfere with target detection +.PHONY: all diff --git a/Make/GNUmakefile b/Make/GNUmakefile new file mode 100644 index 00000000..4b2a73fc --- /dev/null +++ b/Make/GNUmakefile @@ -0,0 +1,401 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file Make/GNUmakefile +# \brief Main orchestrator for openSeaChest modular build system +# +# USAGE: +# make [PLATFORM=linux|windows|freebsd|...] [BUILD_TYPE=release|debug|relwithdebinfo|minsize] [BUILD_JSON=1] [V=1] +# +# EXAMPLES: +# make # Build all (auto-detect platform, release build with -O3) +# make -j$(nproc) # Parallel build with all CPU cores +# make BUILD_TYPE=debug # Debug build (-O0 -g3, no optimization) +# make BUILD_TYPE=release # Release build (-O3, default) +# make BUILD_TYPE=relwithdebinfo # Optimized with debug symbols (-O2 -g) +# make BUILD_TYPE=minsize # Minimize binary size (-Os) +# make BUILD_JSON=1 # Enable JSON support +# make install PREFIX=/usr # Install to /usr instead of /usr/local +# make package # Create distribution tarball +# make show-config # Show build configuration +# make clean # Clean current build type +# make clean-all # Clean all build types +# +#=============================================================================== +# Build System Modules (Order Matters) +#=============================================================================== + +# Determine Make directory for includes +MAKE_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +# 1. Core configuration (platform detection, build directories) +include $(MAKE_DIR)config.mk + +# 2. Compiler detection (GCC/Clang version checks) +include $(MAKE_DIR)compiler-detection.mk + +# 3. Compiler flags (warning flags with cc_supports testing) +include $(MAKE_DIR)compiler-flags.mk + +# 4. Security hardening (OpenSSF best practices) +include $(MAKE_DIR)security-hardening.mk + +# 5. Platform-specific configuration (detect or override) +include $(MAKE_DIR)platforms/$(PLATFORM).mk + +# Set default EXE_EXT if platform didn't define it (Unix platforms = no extension) +EXE_EXT ?= + +# 6. Library build rules (opensea-common, opensea-transport, opensea-operations) +include $(MAKE_DIR)library.mk + +# 7. JSON support (optional, BUILD_JSON=1) +ifeq ($(BUILD_JSON),1) + -include $(MAKE_DIR)jsonformat.mk +endif + +# 8. Tool build rules (17 openSeaChest utilities) +include $(MAKE_DIR)tools.mk + +# 9. Pattern rules and targets (.d dependency tracking, clean, help) +include $(MAKE_DIR)rules.mk + +#=============================================================================== +# Default Target +#=============================================================================== + +.PHONY: all +all: libraries tools + +#=============================================================================== +# Library Targets +#=============================================================================== + +.PHONY: libraries opensea-common opensea-transport opensea-operations + +libraries: opensea-common opensea-transport opensea-operations + +ifeq ($(BUILD_JSON),1) +libraries: opensea-jsonformat +endif + +#=============================================================================== +# Build Type Shortcuts +#=============================================================================== + +.PHONY: release debug relwithdebinfo minsize + +# Prevent parallel execution for these targets to avoid race conditions +# Package and install operations must run serially for filesystem consistency +.NOTPARALLEL: package install install-strip + +release: + $(MAKE) BUILD_TYPE=release + +debug: + $(MAKE) BUILD_TYPE=debug + +relwithdebinfo: + $(MAKE) BUILD_TYPE=relwithdebinfo + +minsize: + $(MAKE) BUILD_TYPE=minsize + +# Legacy shortcuts (deprecated) +.PHONY: static-release static-debug + +static-release: + @echo "Warning: static-release is deprecated. Use BUILD_TYPE=release IS_STATIC=1" + $(MAKE) BUILD_TYPE=release IS_STATIC=1 + +static-debug: + @echo "Warning: static-debug is deprecated. Use BUILD_TYPE=debug IS_STATIC=1" + $(MAKE) BUILD_TYPE=debug IS_STATIC=1 + +#=============================================================================== +# Installation Targets +#=============================================================================== + +# Default installation prefix +PREFIX ?= /usr/local +DESTDIR ?= + +# Installation program (can be overridden for install-strip) +INSTALL_PROGRAM ?= install + +# Installation directories +INSTALL_BIN_DIR := $(DESTDIR)$(PREFIX)/bin +INSTALL_LIB_DIR := $(DESTDIR)$(PREFIX)/lib +INSTALL_INC_DIR := $(DESTDIR)$(PREFIX)/include/opensea + +.PHONY: install uninstall install-tools install-libs install-headers install-strip installdirs + +# Create installation directories (GNU Coding Standards requirement) +installdirs: + @$(call print_status,"Creating installation directories") + @mkdir -p $(INSTALL_BIN_DIR) + @mkdir -p $(INSTALL_LIB_DIR) + @mkdir -p $(INSTALL_INC_DIR) + @$(call print_success,"Installation directories created") + +install: installdirs install-tools install-libs install-headers + @$(call print_success,"Installation complete to $(PREFIX)") + +install-strip: installdirs + @$(call print_status,"Installing stripped binaries to $(PREFIX)") + $(MAKE) INSTALL_PROGRAM='install -s' install-tools + $(MAKE) install-libs install-headers + @$(call print_success,"Installation complete (stripped)") + +install-tools: tools | $(INSTALL_BIN_DIR) + @$(call print_status,"Installing tools to $(INSTALL_BIN_DIR)") + @$(INSTALL_PROGRAM) -m 0755 $(TOOL_EXES) $(INSTALL_BIN_DIR)/ + @$(call print_success,"Installed $(words $(TOOL_EXES)) tools") + +install-libs: libraries | $(INSTALL_LIB_DIR) + @$(call print_status,"Installing libraries to $(INSTALL_LIB_DIR)") + @install -m 0644 $(LIB_DIR)/lib*.a $(INSTALL_LIB_DIR)/ 2>/dev/null || true +ifeq ($(BUILD_SHARED_LIBS),1) + @install -m 0755 $(LIB_DIR)/lib*.so* $(INSTALL_LIB_DIR)/ 2>/dev/null || true +endif + @$(call print_success,"Installed libraries") + +install-headers: | $(INSTALL_INC_DIR) + @$(call print_status,"Installing headers to $(INSTALL_INC_DIR)") + @install -m 0644 $(COMMON_DIR)/include/*.h $(INSTALL_INC_DIR)/ + @install -m 0644 $(TRANSPORT_DIR)/include/*.h $(INSTALL_INC_DIR)/ + @install -m 0644 $(OPERATIONS_DIR)/include/*.h $(INSTALL_INC_DIR)/ + @$(call print_success,"Installed headers") + +# Create installation directories +$(INSTALL_BIN_DIR) $(INSTALL_LIB_DIR) $(INSTALL_INC_DIR): + @mkdir -p $@ + +uninstall: + @$(call print_status,"Uninstalling from $(PREFIX)") + @rm -f $(addprefix $(INSTALL_BIN_DIR)/,$(notdir $(TOOL_EXES))) + @rm -f $(INSTALL_LIB_DIR)/libopensea-*.a $(INSTALL_LIB_DIR)/libopensea-*.so* + @rm -rf $(INSTALL_INC_DIR) + @$(call print_success,"Uninstall complete") + +#=============================================================================== +# Package Target (Create Distribution Tarball) +#=============================================================================== + +# Extract version from git or use default +VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "unknown") +PACKAGE_NAME := openSeaChest-$(VERSION)-$(PLATFORM)-$(ARCH) +PACKAGE_FILE := $(PACKAGE_NAME).tar.gz +PACKAGE_DIR := $(PROJECT_ROOT)/build/package/$(PACKAGE_NAME) + +.PHONY: package + +package: all + @echo "Creating package $(PACKAGE_FILE)..." + @rm -rf $(PROJECT_ROOT)/build/package + @mkdir -p $(PACKAGE_DIR)/bin + @mkdir -p $(PACKAGE_DIR)/lib + @mkdir -p $(PACKAGE_DIR)/include + @cp $(TOOL_EXES) $(PACKAGE_DIR)/bin/ + @cp $(LIB_DIR)/lib*.a $(PACKAGE_DIR)/lib/ 2>/dev/null || true +ifeq ($(BUILD_SHARED_LIBS),1) + @cp $(LIB_DIR)/lib*.so* $(PACKAGE_DIR)/lib/ 2>/dev/null || true +endif + @cp -r $(COMMON_DIR)/include/*.h $(PACKAGE_DIR)/include/ + @cp -r $(TRANSPORT_DIR)/include/*.h $(PACKAGE_DIR)/include/ + @cp -r $(OPERATIONS_DIR)/include/*.h $(PACKAGE_DIR)/include/ + @cp README.md LICENSE.md $(PACKAGE_DIR)/ 2>/dev/null || true + @cd $(PROJECT_ROOT)/build/package && tar czf $(PACKAGE_FILE) $(PACKAGE_NAME) + @mv $(PROJECT_ROOT)/build/package/$(PACKAGE_FILE) $(PROJECT_ROOT)/ + @echo "Package created: $(PACKAGE_FILE)" + +#=============================================================================== +# Utility Targets +#=============================================================================== + +.PHONY: show-config print-tools print-libs + +show-config: + @echo "$(COLOR_HEADER)openSeaChest Build Configuration$(COLOR_RESET)" + @echo "$(COLOR_STATUS)=================================$(COLOR_RESET)" + @echo "Platform: $(PLATFORM)" + @echo "Architecture: $(ARCH)" + @echo "Build Type: $(BUILD_TYPE)" + @echo "Optimization: $(OPTIMIZATION_FLAGS)" + @echo "Defines: $(BUILD_DEFINES)" + @echo "Compiler: $(COMPILER_NAME)" + @echo "Build Dir: $(BUILD_DIR)" + @echo "Output Dirs: bin=$(BIN_DIR) lib=$(LIB_DIR) obj=$(OBJ_DIR)" + @echo "Build JSON: $(if $(filter 1,$(BUILD_JSON)),Yes,No)" + @echo "Shared Libs: $(if $(filter 1,$(BUILD_SHARED_LIBS)),Yes,No)" + @echo "Static Build: $(if $(filter 1,$(IS_STATIC)),Yes,No)" + @echo "Parallel Jobs: $(or $(patsubst -j%,%,$(filter -j%,$(MAKEFLAGS))),1)" + @echo "" + @echo "$(COLOR_STATUS)Compiler Flags:$(COLOR_RESET)" + @echo "CFLAGS: $(CFLAGS)" + @echo "LDFLAGS: $(LDFLAGS)" + @echo "" + +print-tools: + @echo "$(COLOR_HEADER)Tools to Build ($(words $(TOOLS))):$(COLOR_RESET)" + @for tool in $(TOOLS); do echo " - $$tool"; done + +print-libs: + @echo "$(COLOR_HEADER)Libraries to Build:$(COLOR_RESET)" + @echo " - libopensea-common.a" + @echo " - libopensea-transport.a" + @echo " - libopensea-operations.a" +ifeq ($(BUILD_JSON),1) + @echo " - libopensea-jsonformat.a" + @echo " - libjson-c.a (external)" +endif + +# Debug any variable: make print-CFLAGS, make print-BUILD_TYPE, etc. +# Shows value, origin (file/environment/command-line), and flavor (simple/recursive) +.PHONY: print-% +print-%: + @echo '$* = $($*)' + @echo 'Origin: $(origin $*)' + @echo 'Flavor: $(flavor $*)' + +#=============================================================================== +# Clean Targets +#=============================================================================== + +.PHONY: clean clean-all mostlyclean distclean + +mostlyclean: + @echo "Cleaning object files and tools (keeping libraries)..." + @rm -f $(OBJ_DIR_COMMON)/*.o $(OBJ_DIR_COMMON)/*.d 2>/dev/null || true + @rm -f $(OBJ_DIR_TRANSPORT)/*.o $(OBJ_DIR_TRANSPORT)/*.d 2>/dev/null || true + @rm -f $(OBJ_DIR_OPERATIONS)/*.o $(OBJ_DIR_OPERATIONS)/*.d 2>/dev/null || true + @rm -f $(OBJ_DIR_JSONFORMAT)/*.o $(OBJ_DIR_JSONFORMAT)/*.d 2>/dev/null || true + @rm -f $(OBJ_DIR_TOOLS)/*.o $(OBJ_DIR_TOOLS)/*.d 2>/dev/null || true + @rm -f $(BIN_DIR)/* 2>/dev/null || true + @echo "Mostlyclean complete (libraries preserved)" + +clean: + @echo "Cleaning $(BUILD_TYPE) build..." + @rm -rf $(BUILD_DIR) + @echo "Clean complete" + +clean-all: + @echo "Cleaning all build types..." + @rm -rf build/ + @echo "Clean all complete" + +distclean: clean-all + @$(call print_status,"Removing all generated files") + @rm -rf $(PROJECT_ROOT)/*.tar.gz + @find $(PROJECT_ROOT) -name '*.o' -delete 2>/dev/null || true + @find $(PROJECT_ROOT) -name '*.d' -delete 2>/dev/null || true + @$(call print_success,"Distclean complete") + +#=============================================================================== +# Test/Check Target +#=============================================================================== + +.PHONY: check test + +# Smoke tests: verify tools run and respond to --version +check test: tools + @echo "Running basic smoke tests..." + @failed=0; \ + for tool in $(TOOL_EXES); do \ + echo -n " Testing $$(basename $$tool)... "; \ + if $$tool --version >/dev/null 2>&1; then \ + echo "OK"; \ + else \ + echo "FAILED"; \ + failed=$$((failed + 1)); \ + fi; \ + done; \ + if [ $$failed -eq 0 ]; then \ + echo "All $(words $(TOOL_EXES)) tools passed smoke tests"; \ + else \ + echo "$$failed tool(s) failed smoke tests"; \ + exit 1; \ + fi + +#=============================================================================== +# Help Target +#=============================================================================== + +.PHONY: help + +help: + @echo "$(COLOR_HEADER)openSeaChest Build System$(COLOR_RESET)" + @echo "" + @echo "$(COLOR_STATUS)TARGETS:$(COLOR_RESET)" + @echo " all Build all libraries and tools (default)" + @echo " libraries Build only libraries (opensea-common, transport, operations)" + @echo " tools Build only openSeaChest utilities (requires libraries)" + @echo " check / test Run basic smoke tests on built tools" + @echo " install Install binaries, libraries, and headers" + @echo " install-strip Install binaries with debug symbols stripped" + @echo " installdirs Create installation directories only" + @echo " uninstall Remove installed files" + @echo " package Create distribution tarball" + @echo " mostlyclean Clean objects and tools (keep libraries)" + @echo " clean Clean current build type" + @echo " clean-all Clean all build types" + @echo " distclean Remove all generated files including packages" + @echo " show-config Display build configuration" + @echo " print-tools List all tools to build" + @echo " print-libs List all libraries to build" + @echo " help Show this help message" + @echo "" + @echo "$(COLOR_STATUS)BUILD TYPES:$(COLOR_RESET)" + @echo " release Optimized build (-O3, default)" + @echo " debug Debug build (-O0 -g3, no optimization)" + @echo " relwithdebinfo Optimized with debug symbols (-O2 -g)" + @echo " minsize Minimize binary size (-Os)" + @echo "" + @echo "$(COLOR_STATUS)VARIABLES:$(COLOR_RESET)" + @echo " PLATFORM= Override platform detection (linux, windows, freebsd, etc.)" + @echo " BUILD_TYPE= Set build type (release, debug, relwithdebinfo, minsize)" + @echo " BUILD_JSON=1 Enable JSON support (requires CMake and json-c)" + @echo " BUILD_SHARED_LIBS=1 Build shared libraries in addition to static" + @echo " IS_STATIC=1 Build static binaries (link runtime statically)" + @echo " PREFIX=/path Installation prefix (default: /usr/local)" + @echo " DESTDIR=/path Staging directory for installation" + @echo " V=1 Verbose build output" + @echo " CC= Override compiler (gcc, clang)" + @echo "" + @echo "$(COLOR_STATUS)EXAMPLES:$(COLOR_RESET)" + @echo " make # Build all with auto-detected platform (optimized)" + @echo " make -j\$$(nproc) # Parallel build using all CPU cores" + @echo " make BUILD_TYPE=debug # Debug build (no optimization, full debug info)" + @echo " make BUILD_TYPE=relwithdebinfo # Optimized build with debug symbols (for profiling)" + @echo " make BUILD_TYPE=minsize # Smallest binary size (embedded systems)" + @echo " make BUILD_JSON=1 # Build with JSON support" + @echo " make PLATFORM=windows CC=gcc # Cross-compile for Windows" + @echo " make install PREFIX=/usr # Install to /usr instead of /usr/local" + @echo " make package # Create openSeaChest-VERSION-PLATFORM.tar.gz" + @echo " make show-config # Show current configuration" + @echo "" + @echo "$(COLOR_STATUS)SUPPORTED PLATFORMS:$(COLOR_RESET)" + @echo " linux, windows, freebsd, openbsd, netbsd, dragonflybsd," + @echo " sunos, illumos, aix, vmware" + @echo "" + +#=============================================================================== +# Phony Targets Declaration +#=============================================================================== + +.PHONY: all libraries tools \ + release debug static-release static-debug \ + install uninstall install-tools install-libs install-headers \ + package \ + show-config print-tools print-libs \ + clean clean-all distclean \ + help diff --git a/Make/compiler-detection.mk b/Make/compiler-detection.mk new file mode 100644 index 00000000..835cad88 --- /dev/null +++ b/Make/compiler-detection.mk @@ -0,0 +1,226 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file compiler-detection.mk +# \brief Detect compiler type and version for version-specific flags + +#=============================================================================== +# Compiler Detection +#=============================================================================== + +# Detect if using GCC or Clang +COMPILER_ID := $(shell $(CC) --version 2>/dev/null | head -n1) +COMPILER_ID_LOWER := $(shell echo '$(COMPILER_ID)' | tr 'A-Z' 'a-z') + +# GCC detection (case-insensitive) +IS_GCC := 0 +ifneq ($(findstring gcc,$(COMPILER_ID_LOWER)),) + IS_GCC := 1 +endif +ifneq ($(findstring g++,$(COMPILER_ID_LOWER)),) + IS_GCC := 1 +endif +# BSD/Windows systems often have GCC but it identifies as "cc" or "cc.exe" with additional info +# Examples: +# NetBSD: "cc (nb3 20231008) 10.5.0" +# OpenBSD: "cc (GCC) 8.4.0" +# Windows MinGW-Builds: "cc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.2.0" +# MSYS2: "cc.exe (Rev11, Built by MSYS2 project) 15.2.0" +# DragonFlyBSD: "cc 8.3 [DragonFly] Release/2019-02-22" +# Check for patterns that indicate GCC (Note: Use basic grep for Solaris compatibility) +ifneq ($(shell echo '$(COMPILER_ID)' | grep 'cc\.exe .* [0-9]'),) + IS_GCC := 1 +endif +ifneq ($(shell echo '$(COMPILER_ID)' | grep 'cc .* [0-9]'),) + IS_GCC := 1 +endif + +# Clang detection (case-insensitive) +IS_CLANG := 0 +ifneq ($(findstring clang,$(COMPILER_ID_LOWER)),) + IS_CLANG := 1 + # Clang pretends to be GCC, disambiguate + IS_GCC := 0 +endif + +#=============================================================================== +# GCC Version Detection +#=============================================================================== + +# VMware ESXi cross-compiler special case +# VMware's GCC-based cross-compiler doesn't respond to -dumpversion +# Force GCC detection and set a known-good version manually +ifeq ($(PLATFORM),vmware) + IS_GCC := 1 + IS_CLANG := 0 + # TODO: Update this version based on actual VMware DDK GCC version + # This is a placeholder - user will provide the correct version + GCC_VERSION_FULL := 4.9.0 + GCC_MAJOR := 4 + GCC_MINOR := 9 + GCC_PATCH := 0 +endif + +ifeq ($(IS_GCC),1) + # Get GCC version (format: major.minor.patch) + # Skip version detection for VMware (already set above) + ifneq ($(PLATFORM),vmware) + GCC_VERSION_FULL := $(shell $(CC) -dumpversion 2>/dev/null) + endif + + # Get GCC version (format: major.minor.patch) + # Skip version detection for VMware (already set above) + ifneq ($(PLATFORM),vmware) + GCC_VERSION_FULL := $(shell $(CC) -dumpversion 2>/dev/null) + endif + + # Parse major version (strip non-numeric suffixes like "-win32" from MinGW) + # Skip parsing for VMware (already set above) + ifneq ($(PLATFORM),vmware) + GCC_MAJOR := $(shell echo $(GCC_VERSION_FULL) | cut -d. -f1 | sed 's/[^0-9].*//') + endif + + # Parse minor version (default to 0 if not present) + # Skip parsing for VMware (already set above) + ifneq ($(PLATFORM),vmware) + GCC_MINOR := $(shell echo $(GCC_VERSION_FULL) | cut -d. -f2 | sed 's/[^0-9].*//' 2>/dev/null || echo 0) + ifeq ($(GCC_MINOR),) + GCC_MINOR := 0 + endif + endif + + # Parse patch version (default to 0 if not present) + # Skip parsing for VMware (already set above) + ifneq ($(PLATFORM),vmware) + GCC_PATCH := $(shell echo $(GCC_VERSION_FULL) | cut -d. -f3 | sed 's/[^0-9].*//' 2>/dev/null || echo 0) + ifeq ($(GCC_PATCH),) + GCC_PATCH := 0 + endif + endif + + # Combined version for comparisons (e.g., 40900 for 4.9.0) + GCC_VERSION_NUM := $(shell printf "%d%02d%02d" $(GCC_MAJOR) $(GCC_MINOR) $(GCC_PATCH) 2>/dev/null || echo 0) + + # Version checks (for conditional flag support) + GCC_AT_LEAST_4_7 := $(shell [ $(GCC_MAJOR) -gt 4 -o \( $(GCC_MAJOR) -eq 4 -a $(GCC_MINOR) -ge 7 \) ] && echo 1 || echo 0) + GCC_AT_LEAST_4_8 := $(shell [ $(GCC_MAJOR) -gt 4 -o \( $(GCC_MAJOR) -eq 4 -a $(GCC_MINOR) -ge 8 \) ] && echo 1 || echo 0) + GCC_AT_LEAST_4_9 := $(shell [ $(GCC_MAJOR) -gt 4 -o \( $(GCC_MAJOR) -eq 4 -a $(GCC_MINOR) -ge 9 \) ] && echo 1 || echo 0) + GCC_AT_LEAST_5 := $(shell [ $(GCC_MAJOR) -ge 5 ] && echo 1 || echo 0) + GCC_AT_LEAST_6 := $(shell [ $(GCC_MAJOR) -ge 6 ] && echo 1 || echo 0) + GCC_AT_LEAST_7 := $(shell [ $(GCC_MAJOR) -ge 7 ] && echo 1 || echo 0) + GCC_AT_LEAST_8 := $(shell [ $(GCC_MAJOR) -ge 8 ] && echo 1 || echo 0) + GCC_AT_LEAST_9 := $(shell [ $(GCC_MAJOR) -ge 9 ] && echo 1 || echo 0) + GCC_AT_LEAST_10 := $(shell [ $(GCC_MAJOR) -ge 10 ] && echo 1 || echo 0) + GCC_AT_LEAST_11 := $(shell [ $(GCC_MAJOR) -ge 11 ] && echo 1 || echo 0) + GCC_AT_LEAST_12 := $(shell [ $(GCC_MAJOR) -ge 12 ] && echo 1 || echo 0) + GCC_AT_LEAST_13 := $(shell [ $(GCC_MAJOR) -ge 13 ] && echo 1 || echo 0) + GCC_AT_LEAST_14 := $(shell [ $(GCC_MAJOR) -ge 14 ] && echo 1 || echo 0) + + COMPILER_NAME := GCC $(GCC_VERSION_FULL) +else + GCC_VERSION_FULL := 0.0.0 + GCC_MAJOR := 0 + GCC_MINOR := 0 + GCC_PATCH := 0 + GCC_VERSION_NUM := 0 + GCC_AT_LEAST_4_7 := 0 + GCC_AT_LEAST_4_8 := 0 + GCC_AT_LEAST_4_9 := 0 + GCC_AT_LEAST_5 := 0 + GCC_AT_LEAST_6 := 0 + GCC_AT_LEAST_7 := 0 + GCC_AT_LEAST_8 := 0 + GCC_AT_LEAST_9 := 0 + GCC_AT_LEAST_10 := 0 + GCC_AT_LEAST_11 := 0 + GCC_AT_LEAST_12 := 0 + GCC_AT_LEAST_13 := 0 + GCC_AT_LEAST_14 := 0 +endif + +#=============================================================================== +# Clang Version Detection +#=============================================================================== + +ifeq ($(IS_CLANG),1) + # Get Clang version (format: "clang version major.minor.patch") + CLANG_VERSION_OUTPUT := $(shell $(CC) --version 2>/dev/null | head -n1) + CLANG_VERSION_FULL := $(shell echo "$(CLANG_VERSION_OUTPUT)" | sed -n 's/.*version \([0-9.]*\).*/\1/p') + + # Parse major version + CLANG_MAJOR := $(shell echo $(CLANG_VERSION_FULL) | cut -d. -f1) + + # Parse minor version (default to 0 if not present) + CLANG_MINOR := $(shell echo $(CLANG_VERSION_FULL) | cut -d. -f2 2>/dev/null || echo 0) + + # Parse patch version (default to 0 if not present) + CLANG_PATCH := $(shell echo $(CLANG_VERSION_FULL) | cut -d. -f3 2>/dev/null || echo 0) + + # Combined version for comparisons + CLANG_VERSION_NUM := $(shell printf "%d%02d%02d" $(CLANG_MAJOR) $(CLANG_MINOR) $(CLANG_PATCH) 2>/dev/null || echo 0) + + # Version checks (for conditional flag support) + CLANG_AT_LEAST_3_0 := $(shell [ $(CLANG_MAJOR) -ge 3 ] && echo 1 || echo 0) + CLANG_AT_LEAST_3_5 := $(shell [ $(CLANG_MAJOR) -gt 3 -o \( $(CLANG_MAJOR) -eq 3 -a $(CLANG_MINOR) -ge 5 \) ] && echo 1 || echo 0) + CLANG_AT_LEAST_5 := $(shell [ $(CLANG_MAJOR) -ge 5 ] && echo 1 || echo 0) + CLANG_AT_LEAST_7 := $(shell [ $(CLANG_MAJOR) -ge 7 ] && echo 1 || echo 0) + CLANG_AT_LEAST_10 := $(shell [ $(CLANG_MAJOR) -ge 10 ] && echo 1 || echo 0) + CLANG_AT_LEAST_12 := $(shell [ $(CLANG_MAJOR) -ge 12 ] && echo 1 || echo 0) + CLANG_AT_LEAST_14 := $(shell [ $(CLANG_MAJOR) -ge 14 ] && echo 1 || echo 0) + CLANG_AT_LEAST_16 := $(shell [ $(CLANG_MAJOR) -ge 16 ] && echo 1 || echo 0) + CLANG_AT_LEAST_18 := $(shell [ $(CLANG_MAJOR) -ge 18 ] && echo 1 || echo 0) + + COMPILER_NAME := Clang $(CLANG_VERSION_FULL) +else + CLANG_VERSION_FULL := 0.0.0 + CLANG_MAJOR := 0 + CLANG_MINOR := 0 + CLANG_PATCH := 0 + CLANG_VERSION_NUM := 0 + CLANG_AT_LEAST_3_0 := 0 + CLANG_AT_LEAST_3_5 := 0 + CLANG_AT_LEAST_5 := 0 + CLANG_AT_LEAST_7 := 0 + CLANG_AT_LEAST_10 := 0 + CLANG_AT_LEAST_12 := 0 + CLANG_AT_LEAST_14 := 0 + CLANG_AT_LEAST_16 := 0 + CLANG_AT_LEAST_18 := 0 +endif + +#=============================================================================== +# Compiler Unknown Warning +#=============================================================================== + +ifeq ($(IS_GCC)$(IS_CLANG),00) + COMPILER_NAME := Unknown ($(COMPILER_ID)) + $(warning Unknown compiler detected: $(COMPILER_ID)) + $(warning Build may fail. Supported compilers: GCC, Clang) +endif + +#=============================================================================== +# Export Variables +#=============================================================================== + +export IS_GCC +export IS_CLANG +export GCC_VERSION_FULL +export GCC_MAJOR +export GCC_MINOR +export GCC_PATCH +export GCC_VERSION_NUM +export CLANG_VERSION_FULL +export CLANG_MAJOR +export CLANG_MINOR +export CLANG_PATCH +export CLANG_VERSION_NUM +export COMPILER_NAME diff --git a/Make/compiler-flags.mk b/Make/compiler-flags.mk new file mode 100644 index 00000000..c3bdeb2f --- /dev/null +++ b/Make/compiler-flags.mk @@ -0,0 +1,370 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file compiler-flags.mk +# \brief Warning flags from meson.build with compatibility testing +# \note Flags extracted from meson.build April 4, 2024 +# \note Reference: https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++ + +#=============================================================================== +# Compiler Flag Support Testing +#=============================================================================== + +# Test if compiler supports a flag (mirrors Meson's get_supported_arguments) +# Returns "yes" if supported, empty if not +# Usage: $(call cc_supports,-Wflag-name) +# Note: Outputs "[compiler] Checking: flag" to stderr so user sees progress +cc_supports = $(shell \ + echo "[$(CC)] Checking: $(1)" >&2; \ + echo 'int main(void) { return 0; }' | \ + $(CC) $(1) -Werror -x c - -o /dev/null 2>/dev/null && echo yes) + +# Cache file for tested flags +COMPILER_FLAGS_CACHE := $(BUILD_DIR)/.compiler-flags-cache + +# Create build directory if needed +$(shell mkdir -p $(BUILD_DIR) 2>/dev/null) + +#=============================================================================== +# Base Warning Flags (GCC 4.7+ and Clang 3.5+ known-good, no testing needed) +#=============================================================================== + +BASE_WARNING_FLAGS := \ + -Wall \ + -Wextra \ + -Wformat=2 \ + -Werror=format-security \ + -Wnull-dereference \ + -Wunused-const-variable \ + -Wunused-parameter \ + -Wunused-value \ + -Wfloat-equal \ + -Wvla \ + -Wdouble-promotion \ + -Wold-style-definition \ + -Wstrict-prototypes \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wchar-subscripts \ + -Wundef \ + -Wformat \ + -Wimplicit-fallthrough \ + -Werror=implicit \ + -Werror=int-conversion \ + -Werror=implicit-int \ + -Wparentheses \ + -Wcast-qual \ + -Wuninitialized \ + -Wvarargs \ + -Wwrite-strings \ + -Wcomment \ + -Wsequence-point \ + -Wreturn-type + +#=============================================================================== +# Newer Warning Flags (require version checks or testing) +#=============================================================================== + +# GCC-specific newer flags (test for support) +NEWER_WARNING_CANDIDATES_GCC := \ + -Wshadow=compatible-local \ + -Wduplicated-cond \ + -Wjump-misses-init \ + -Wstringop-overflow \ + -Wlogical-op \ + -Wshift-overflow=2 \ + -Wrestrict \ + -Wstringop-truncation \ + -Wtrampolines \ + -Wmismatched-dealloc \ + -Wfree-nonheap-object + +# Clang-specific newer flags (test for support) +NEWER_WARNING_CANDIDATES_CLANG := \ + -Wincompatible-pointer-types-discards-qualifiers \ + -Woverlength-strings \ + -Wnewline-eof \ + -Wextra-semi \ + -Werror=sometimes-uninitialized \ + -Wunevaluated-expression \ + -Wunsequenced \ + -Wunreachable-code \ + -Wpointer-bool-conversion \ + -Wnullability \ + -Wnullability-completeness \ + -Wnullability-completeness-on-arrays + +# Common newer flags (both GCC and Clang, test for support) +NEWER_WARNING_CANDIDATES_COMMON := \ + -Werror=incompatible-pointer-types \ + -Werror=trigraphs \ + -Walloc-zero \ + -Walloc-size \ + -Wcalloc-transposed-args \ + -Werror=alloca \ + -Wstring-compare + +# Test newer flags based on compiler +ifeq ($(IS_GCC),1) + NEWER_WARNING_CANDIDATES := $(NEWER_WARNING_CANDIDATES_GCC) $(NEWER_WARNING_CANDIDATES_COMMON) +else ifeq ($(IS_CLANG),1) + NEWER_WARNING_CANDIDATES := $(NEWER_WARNING_CANDIDATES_CLANG) $(NEWER_WARNING_CANDIDATES_COMMON) +else + NEWER_WARNING_CANDIDATES := $(NEWER_WARNING_CANDIDATES_COMMON) +endif + +# Only perform compiler flag checking if we're not cleaning +# Check MAKECMDGOALS to avoid testing during clean, distclean, mostlyclean, etc. +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + # Skipping compiler checks during clean targets +else +# Progress message before testing +$(info Testing compiler warning flag support (this may take a moment)...) + +# Test each flag and collect supported ones +NEWER_WARNINGS := $(foreach flag,$(NEWER_WARNING_CANDIDATES),$(if $(call cc_supports,$(flag)),$(flag))) + +$(info Compiler feature detection complete) +endif + +#=============================================================================== +# Conversion Warnings (test for support, some require newer compilers) +#=============================================================================== + +# Always available conversion warnings +CONVERSION_WARNING_FLAGS := \ + -Wint-conversion \ + -Wfloat-conversion \ + -Wint-to-pointer-cast + +# Test for -Wenum-conversion (GCC 10+, Clang 3.2+) +# Only perform conversion flag checking if we're not cleaning +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + # Skipping conversion checks during clean targets +else +$(info Testing conversion warning flags...) +ifeq ($(call cc_supports,-Wenum-conversion),yes) + CONVERSION_WARNING_FLAGS += -Wenum-conversion +endif +endif + +# GCC 10+ specific: -Wsign-conversion (very noisy, use while debugging) +# NOTE: Intentionally not enabled by default per meson.build comments +# Uncomment if desired: +# ifeq ($(GCC_AT_LEAST_10),1) +# CONVERSION_WARNING_FLAGS += -Wsign-conversion +# endif + +#=============================================================================== +# Common Defines and Flags +#=============================================================================== + +# GLibC++ assertions for C++ (if building any C++ code) +COMMON_DEFINES := -D_GLIBCXX_ASSERTIONS + +# Strict flex arrays (GCC 13+, Clang 16+) +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + STRICT_FLEX_ARRAYS := +else + STRICT_FLEX_ARRAYS := $(call cc_supports,-fstrict-flex-arrays=3) +endif +ifneq ($(STRICT_FLEX_ARRAYS),) + COMMON_FLAGS += -fstrict-flex-arrays=3 +endif + +# Safe null pointer handling +COMMON_FLAGS += -fno-delete-null-pointer-checks + +# Prevent aggressive optimizations that violate C standard +COMMON_FLAGS += -fno-strict-overflow -fno-strict-aliasing + +# Zero-initialize automatic variables +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + ZERO_INIT_AUTO_VAR := +else + ZERO_INIT_AUTO_VAR := $(call cc_supports,-ftrivial-auto-var-init=zero) +endif +ifneq ($(ZERO_INIT_AUTO_VAR),) + COMMON_FLAGS += -ftrivial-auto-var-init=zero +endif + +# Zero-initialize padding bits (GCC 14+, Clang 18+) +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + ZERO_INIT_PADDING := +else + ZERO_INIT_PADDING := $(call cc_supports,-fzero-init-padding-bits=all) +endif +ifneq ($(ZERO_INIT_PADDING),) + COMMON_FLAGS += -fzero-init-padding-bits=all +endif + +# Hidden visibility (works like Windows DLL import/export) +COMMON_FLAGS += -fvisibility=hidden + +# Disable C23 extensions warning (we check availability before use) +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + NO_C23_EXT := +else + NO_C23_EXT := $(call cc_supports,-Wno-c23-extensions) +endif +ifneq ($(NO_C23_EXT),) + COMMON_FLAGS += -Wno-c23-extensions +endif + +#=============================================================================== +# Combined Warning Flags +#=============================================================================== + +WARNING_FLAGS := $(BASE_WARNING_FLAGS) $(NEWER_WARNINGS) $(CONVERSION_WARNING_FLAGS) + +# Add common flags +WARNING_FLAGS += $(COMMON_DEFINES) $(COMMON_FLAGS) + +#=============================================================================== +# Optimization-Level Flags (Build-Type Specific) +#=============================================================================== + +# Use optimization flags from config.mk (based on BUILD_TYPE) +# - debug: -O0 -g3 +# - release: -O3 +# - relwithdebinfo: -O2 -g +# - minsize: -Os +OPT_FLAGS := $(OPTIMIZATION_FLAGS) + +# Add frame pointer for debugging (even in optimized builds) +ifeq ($(BUILD_TYPE),debug) + OPT_FLAGS += -fno-omit-frame-pointer +else ifeq ($(BUILD_TYPE),relwithdebinfo) + # Keep frame pointer for profiling + OPT_FLAGS += -fno-omit-frame-pointer +endif + +# Use build defines from config.mk (based on BUILD_TYPE) +DEBUG_FLAGS := $(BUILD_DEFINES) + +# Link-time optimization for release and minsize builds +# Try -flto=auto first (parallelizes LTRANS across available cores, GCC 10+ / Clang 10+) +# Fallback to -flto if -flto=auto not supported (older compilers) +# Disabled on BSD systems due to ar/ranlib plugin issues +ifeq ($(filter $(BUILD_TYPE),release minsize),$(BUILD_TYPE)) + ifneq ($(filter $(PLATFORM),freebsd openbsd netbsd dragonflybsd),$(PLATFORM)) + ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + LTO_FLAG := + else + # First try -flto=auto (parallel LTO) + LTO_FLAG := $(call cc_supports,-flto=auto) + ifeq ($(LTO_FLAG),) + # Fallback to -flto if -flto=auto not supported + LTO_FLAG := $(call cc_supports,-flto) + # Convert 'yes' to '-flto' + ifeq ($(LTO_FLAG),yes) + LTO_FLAG := -flto + else + LTO_FLAG := + endif + else + # Convert 'yes' to '-flto=auto' + ifeq ($(LTO_FLAG),yes) + LTO_FLAG := -flto=auto + endif + endif + endif + ifneq ($(LTO_FLAG),) + OPT_FLAGS += $(LTO_FLAG) + # Need to pass LTO flag to linker too + LDFLAGS += $(LTO_FLAG) + endif + endif +endif + +#=============================================================================== +# Platform-Specific Flag Adjustments +#=============================================================================== + +# MinGW/Windows specific +ifeq ($(PLATFORM),windows) + # Use MinGW ANSI stdio for proper printf format checking + WARNING_FLAGS += -D__USE_MINGW_ANSI_STDIO=1 + + # Suppress Windows CRT secure warnings (we use safe_ functions from opensea-common) + WARNING_FLAGS += -D_CRT_SECURE_NO_WARNINGS + + # Limit Windows API to Windows 7 (0x0601) for compatibility + # This prevents use of newer APIs like STORAGE_HW_FIRMWARE_INFO_QUERY (Win10+) + # that aren't available in older toolchains + WARNING_FLAGS += -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 + + # MinGW builds need NO_FILE_ID_INFO to work around API issues + # FILE_ID_INFO is not reliably available across all MinGW toolchains + WARNING_FLAGS += -DNO_FILE_ID_INFO +endif + +# DragonFlyBSD specific +ifeq ($(PLATFORM),dragonflybsd) + # DragonFlyBSD doesn't have dev/nvme/nvme.h header, disable NVMe passthrough + WARNING_FLAGS += -DDISABLE_NVME_PASSTHROUGH +endif + +# NetBSD/OpenBSD specific +ifeq ($(filter $(PLATFORM),netbsd openbsd),$(PLATFORM)) + # NetBSD/OpenBSD don't have NVMe ioctl headers, disable NVMe passthrough + WARNING_FLAGS += -DDISABLE_NVME_PASSTHROUGH +endif + +# MUSL libc specific +ifeq ($(USING_MUSL),1) + # MUSL doesn't have certain GLibC features + WARNING_FLAGS := $(filter-out -D_GLIBCXX_ASSERTIONS,$(WARNING_FLAGS)) +endif + +#=============================================================================== +# Combined CFLAGS and CXXFLAGS +#=============================================================================== + +# Initialize if not already set (allows user to provide CFLAGS/CXXFLAGS from environment) +CFLAGS ?= +CXXFLAGS ?= +LDFLAGS ?= + +# Prepend our flags (our flags first, then user flags - this allows user to override) +# Use := for one-time expansion to avoid recursive evaluation issues +CFLAGS := $(WARNING_FLAGS) $(OPT_FLAGS) $(DEBUG_FLAGS) $(CFLAGS) +CXXFLAGS := $(WARNING_FLAGS) $(OPT_FLAGS) $(DEBUG_FLAGS) $(CXXFLAGS) + +# Note: LDFLAGS is only initialized here, actual flags are added in security-hardening.mk and other files + +#=============================================================================== +# Save Tested Flags to Cache (for debugging) +#=============================================================================== + +.PHONY: save-flag-cache +save-flag-cache: + @echo "# Compiler flag test cache" > $(COMPILER_FLAGS_CACHE) + @echo "# Generated: $(shell date)" >> $(COMPILER_FLAGS_CACHE) + @echo "# Compiler: $(COMPILER_NAME)" >> $(COMPILER_FLAGS_CACHE) + @echo "" >> $(COMPILER_FLAGS_CACHE) + @echo "Supported newer flags:" >> $(COMPILER_FLAGS_CACHE) + @$(foreach flag,$(NEWER_WARNINGS),echo " $(flag)" >> $(COMPILER_FLAGS_CACHE);) + @echo "" >> $(COMPILER_FLAGS_CACHE) + @echo "Unsupported flags:" >> $(COMPILER_FLAGS_CACHE) + @$(foreach flag,$(NEWER_WARNING_CANDIDATES),\ + $(if $(filter $(flag),$(NEWER_WARNINGS)),,echo " $(flag)" >> $(COMPILER_FLAGS_CACHE);)) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export WARNING_FLAGS +export OPT_FLAGS +export DEBUG_FLAGS +export CFLAGS +export CXXFLAGS diff --git a/Make/config.mk b/Make/config.mk new file mode 100644 index 00000000..86854f77 --- /dev/null +++ b/Make/config.mk @@ -0,0 +1,486 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file config.mk +# \brief Platform detection, build configuration, and directory structure + +# GNU Make 3.81 or later required +MAKE_VERSION_REQUIRED := 3.81 +MAKE_VERSION_CURRENT := $(MAKE_VERSION) + +ifeq ($(filter $(MAKE_VERSION_REQUIRED),$(firstword $(sort $(MAKE_VERSION_CURRENT) $(MAKE_VERSION_REQUIRED)))),) + $(error GNU Make $(MAKE_VERSION_REQUIRED) or later required. Current: $(MAKE_VERSION_CURRENT)) +endif + +# Project root (parent of Make/ directory) +MAKE_ROOT := $(dir $(lastword $(MAKEFILE_LIST))) +PROJECT_ROOT := $(abspath $(MAKE_ROOT)/..) + +# Fail on undefined variables +MAKEFLAGS += --warn-undefined-variables + +# Use one shell for entire recipe (security + performance) +.ONESHELL: + +# Delete target files if recipe fails (prevents incomplete/corrupted files) +.DELETE_ON_ERROR: + +# Safe shell with error handling +# Prefer bash for pipefail support (catches errors in pipes), fall back to POSIX sh +# NOTE: bash is recommended for best error detection. Install with: +# - Linux/BSD: pkg install bash (or apt/yum/dnf install bash) +# - AIX: installp -a -d . bash (from AIX Toolbox) +# - HP-UX: swinstall bash (from HP-UX porting centre) +# - Solaris: pkg install bash +SHELL := $(shell command -v bash 2>/dev/null || echo sh) +.SHELLFLAGS := $(if $(findstring bash,$(SHELL)),-eu -o pipefail -c,-eu -c) + +#=============================================================================== +# Platform Detection +#=============================================================================== + +# Detect operating system +UNAME_S := $(shell uname -s 2>/dev/null || echo unknown) +UNAME_M := $(shell uname -m 2>/dev/null || echo unknown) + +# Detect host platform (where we're building, not what we're building for) +ifeq ($(findstring Linux,$(UNAME_S)),Linux) + HOST_PLATFORM := linux +else ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) + HOST_PLATFORM := windows +else ifeq ($(findstring MSYS,$(UNAME_S)),MSYS) + HOST_PLATFORM := windows +else ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN) + HOST_PLATFORM := windows +else ifeq ($(findstring FreeBSD,$(UNAME_S)),FreeBSD) + HOST_PLATFORM := freebsd +else + HOST_PLATFORM := $(UNAME_S) +endif + +# Check for VMware ESXi build environment first (special case) +# Note: Use basic grep for Solaris compatibility (no -E support) +HAS_VMWARE_DDK := $(shell rpm -qa 2>/dev/null | grep 'vmware-esx-.*ddk-devtools' || true) + +# Check if using MinGW cross-compiler (e.g., x86_64-w64-mingw32-gcc on Linux) +CC_NAME := $(shell $(CC) --version 2>/dev/null | head -n1) +IS_MINGW_CC := $(findstring mingw,$(CC_NAME)) + +# Detect if cross-compiling (MinGW on non-Windows host) +CROSS_COMPILING := 0 +ifneq ($(IS_MINGW_CC),) + ifneq ($(HOST_PLATFORM),windows) + CROSS_COMPILING := 1 + endif +endif + +# Platform detection (simplified to avoid nested function issues) +ifdef HAS_VMWARE_DDK + PLATFORM_DETECTED := vmware +else ifneq ($(IS_MINGW_CC),) + # Auto-detect MinGW cross-compilation (e.g., x86_64-w64-mingw32-gcc on Linux) + PLATFORM_DETECTED := windows +else ifeq ($(findstring Linux,$(UNAME_S)),Linux) + PLATFORM_DETECTED := linux +else ifeq ($(findstring Darwin,$(UNAME_S)),Darwin) + PLATFORM_DETECTED := macos +else ifeq ($(findstring FreeBSD,$(UNAME_S)),FreeBSD) + PLATFORM_DETECTED := freebsd +else ifeq ($(findstring OpenBSD,$(UNAME_S)),OpenBSD) + PLATFORM_DETECTED := openbsd +else ifeq ($(findstring NetBSD,$(UNAME_S)),NetBSD) + PLATFORM_DETECTED := netbsd +else ifeq ($(findstring DragonFly,$(UNAME_S)),DragonFly) + PLATFORM_DETECTED := dragonflybsd +else ifeq ($(findstring SunOS,$(UNAME_S)),SunOS) + PLATFORM_DETECTED := sunos +else ifeq ($(findstring AIX,$(UNAME_S)),AIX) + PLATFORM_DETECTED := aix +else ifeq ($(findstring HP-UX,$(UNAME_S)),HP-UX) + PLATFORM_DETECTED := hpux +else ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) + PLATFORM_DETECTED := windows +else ifeq ($(findstring MSYS,$(UNAME_S)),MSYS) + PLATFORM_DETECTED := windows +else ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN) + PLATFORM_DETECTED := windows +else + PLATFORM_DETECTED := unknown +endif + +# Set PLATFORM (user can override with PLATFORM=xxx) +PLATFORM ?= $(PLATFORM_DETECTED) + +# Validate platform +SUPPORTED_PLATFORMS := linux windows freebsd openbsd netbsd dragonflybsd sunos aix hpux vmware macos +ifeq ($(filter $(PLATFORM),$(SUPPORTED_PLATFORMS)),) + $(error Unsupported PLATFORM=$(PLATFORM). Supported: $(SUPPORTED_PLATFORMS)) +endif + +# Detect kernel for Solaris/Illumos distinction +ifeq ($(PLATFORM),sunos) + KERNEL := $(shell uname -v 2>/dev/null | grep -qi illumos && echo illumos || echo solaris) +else + KERNEL := $(PLATFORM) +endif + +#=============================================================================== +# Architecture Detection +#=============================================================================== + +# Architecture mapping (simplified) +ifeq ($(findstring x86_64,$(UNAME_M)),x86_64) + ARCH_DETECTED := x86_64 +else ifeq ($(findstring amd64,$(UNAME_M)),amd64) + ARCH_DETECTED := x86_64 +else ifeq ($(findstring i686,$(UNAME_M)),i686) + ARCH_DETECTED := i686 +else ifeq ($(findstring i386,$(UNAME_M)),i386) + ARCH_DETECTED := i686 +else ifeq ($(findstring aarch64,$(UNAME_M)),aarch64) + ARCH_DETECTED := aarch64 +else ifeq ($(findstring arm64,$(UNAME_M)),arm64) + ARCH_DETECTED := aarch64 +else ifeq ($(findstring armv7,$(UNAME_M)),armv7) + ARCH_DETECTED := armv7l +else ifeq ($(findstring ppc64le,$(UNAME_M)),ppc64le) + ARCH_DETECTED := powerpc64le +else ifeq ($(findstring ppc64,$(UNAME_M)),ppc64) + ARCH_DETECTED := powerpc64 +else ifeq ($(findstring riscv64,$(UNAME_M)),riscv64) + ARCH_DETECTED := riscv64 +else + ARCH_DETECTED := $(UNAME_M) +endif + +ARCH ?= $(ARCH_DETECTED) + +#=============================================================================== +# Compiler Selection +#=============================================================================== + +# Auto-detect compiler +# On Solaris/Illumos, prefer gcc/clang if available, otherwise fall back to cc +# This avoids issues where 'cc' may not be in PATH on some Solaris installations +ifeq ($(PLATFORM_DETECTED),sunos) + # Check for gcc first, then clang, then cc + HAS_GCC := $(shell command -v gcc 2>/dev/null) + HAS_CLANG := $(shell command -v clang 2>/dev/null) + ifneq ($(HAS_GCC),) + CC ?= gcc + CXX ?= g++ + else ifneq ($(HAS_CLANG),) + CC ?= clang + CXX ?= clang++ + else + CC ?= cc + CXX ?= c++ + endif +else + # All other platforms: use cc by default (respects system defaults) + CC ?= cc + CXX ?= c++ +endif + +# Export CC/CXX immediately so compiler-detection.mk uses the correct compiler +export CC +export CXX + +#=============================================================================== +# Build Configuration +#=============================================================================== + +# Build type: debug, release, relwithdebinfo, minsize +# Matches Meson's --buildtype options for consistency +BUILD_TYPE ?= release +VALID_BUILD_TYPES := debug release relwithdebinfo minsize + +ifeq ($(filter $(BUILD_TYPE),$(VALID_BUILD_TYPES)),) + $(error Invalid BUILD_TYPE=$(BUILD_TYPE). Valid: $(VALID_BUILD_TYPES)) +endif + +# Optimization and debug flags based on build type +# Use ?= so downstream packagers can override (e.g., OPTIMIZATION_FLAGS="-O2" make) +ifeq ($(BUILD_TYPE),debug) + # No optimization, maximum debug information + OPTIMIZATION_FLAGS ?= -O0 -g3 + BUILD_DEFINES ?= -DDEBUG -D_DEBUG +else ifeq ($(BUILD_TYPE),release) + # Full optimization, no debug info + OPTIMIZATION_FLAGS ?= -O3 + BUILD_DEFINES ?= -DNDEBUG -DRELEASE +else ifeq ($(BUILD_TYPE),relwithdebinfo) + # Optimized with debug symbols (for production debugging/profiling) + OPTIMIZATION_FLAGS ?= -O2 -g + BUILD_DEFINES ?= -DNDEBUG +else ifeq ($(BUILD_TYPE),minsize) + # Optimize for binary size + OPTIMIZATION_FLAGS ?= -Os + BUILD_DEFINES ?= -DNDEBUG +endif + +# Legacy support for static builds (deprecated, use IS_STATIC variable instead) +IS_STATIC ?= 0 + +# Legacy IS_DEBUG flag (derived from BUILD_TYPE for backward compatibility) +IS_DEBUG := $(if $(filter debug,$(BUILD_TYPE)),1,0) + +# Feature flags (user-overridable) +BUILD_JSON ?= 0 +BUILD_SHARED_LIBS ?= 0 +USING_MUSL ?= 0 + +# Validate BUILD_JSON +ifeq ($(BUILD_JSON),1) + HAS_CMAKE := $(shell command -v cmake 2>/dev/null) + ifeq ($(HAS_CMAKE),) + $(error BUILD_JSON=1 requires CMake but cmake was not found in PATH) + endif +endif + +#=============================================================================== +# Reproducible Builds Support +# Reference: https://reproducible-builds.org/docs/source-date-epoch/ +#=============================================================================== + +# SOURCE_DATE_EPOCH: Unix timestamp for reproducible builds +# If set, use it for BUILD_TIMESTAMP; otherwise use current date/time +# This supports reproducible builds while maintaining compatibility +ifdef SOURCE_DATE_EPOCH + # Use SOURCE_DATE_EPOCH if set (for reproducible builds) + # Try GNU date format first (-d flag), fall back to BSD date format (-r flag) + BUILD_TIMESTAMP := $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" 2>/dev/null || date -u) +else + # Use current date/time if SOURCE_DATE_EPOCH not set + BUILD_TIMESTAMP := $(shell date -u) +endif + +# Export for use in build flags if needed +export BUILD_TIMESTAMP + +#=============================================================================== +# Build Directories +#=============================================================================== + +# Build directory structure: build/platform-arch-buildtype/ +BUILD_DIR_NAME := $(PLATFORM)-$(ARCH)-$(BUILD_TYPE) +BUILD_DIR := $(PROJECT_ROOT)/build/$(BUILD_DIR_NAME) + +# Subdirectories +OBJ_DIR := $(BUILD_DIR)/obj +LIB_DIR := $(BUILD_DIR)/lib +BIN_DIR := $(BUILD_DIR)/bin + +# Object file subdirectories (one per library/module) +OBJ_DIR_COMMON := $(OBJ_DIR)/common +OBJ_DIR_TRANSPORT := $(OBJ_DIR)/transport +OBJ_DIR_OPERATIONS := $(OBJ_DIR)/operations +OBJ_DIR_JSONFORMAT := $(OBJ_DIR)/jsonformat +OBJ_DIR_TOOLS := $(OBJ_DIR)/tools + +# All object directories (for order-only prerequisites) +OBJ_DIRS := $(OBJ_DIR_COMMON) $(OBJ_DIR_TRANSPORT) $(OBJ_DIR_OPERATIONS) \ + $(OBJ_DIR_JSONFORMAT) $(OBJ_DIR_TOOLS) + +# Create directories target +$(OBJ_DIR) $(LIB_DIR) $(BIN_DIR) $(OBJ_DIRS): + @mkdir -p $@ + +#=============================================================================== +# Build System Dependencies +#=============================================================================== + +# Automatically rebuild all targets if build configuration changes +# This ensures clean rebuilds when compiler flags, security settings, etc. change +.EXTRA_PREREQS := $(MAKE_ROOT)config.mk $(MAKE_ROOT)compiler-flags.mk $(MAKE_ROOT)security-hardening.mk + +#=============================================================================== +# Toolchain +#=============================================================================== + +# Compiler and tools +# Auto-detect system default compiler (cc points to gcc or clang depending on system) +# FreeBSD/OpenBSD use clang by default, most Linux use gcc +# Solaris doesn't have 'cc' by default, use gcc +# Only override if CC is unset (not if it's already set to 'cc') +ifeq ($(PLATFORM),sunos) + CC ?= gcc + CXX ?= g++ +else + CC ?= cc + CXX ?= c++ +endif +AR ?= ar +STRIP ?= strip +INSTALL ?= install + +# Ranlib (some platforms need it) +RANLIB ?= ranlib + +#=============================================================================== +# Installation Directories +#=============================================================================== + +# Installation prefix (user-overridable) +PREFIX ?= /usr/local +DESTDIR ?= + +# Standard installation directories +BINDIR := $(PREFIX)/bin +LIBDIR := $(PREFIX)/lib +INCLUDEDIR := $(PREFIX)/include +MANDIR := $(PREFIX)/share/man +MAN8DIR := $(MANDIR)/man8 + +#=============================================================================== +# Source Directories +#=============================================================================== + +# Subproject source directories +COMMON_DIR := $(PROJECT_ROOT)/subprojects/opensea-common +TRANSPORT_DIR := $(PROJECT_ROOT)/subprojects/opensea-transport +OPERATIONS_DIR := $(PROJECT_ROOT)/subprojects/opensea-operations +JSONFORMAT_DIR := $(PROJECT_ROOT)/subprojects/opensea-jsonformat +WINGETOPT_DIR := $(PROJECT_ROOT)/subprojects/wingetopt +JSONC_DIR := $(PROJECT_ROOT)/subprojects/json-c + +# Utility source directory +UTILS_DIR := $(PROJECT_ROOT)/utils/C/openSeaChest + +# Common project source files +PROJECT_SRC_DIR := $(PROJECT_ROOT)/src + +#=============================================================================== +# Library Versions +#=============================================================================== + +# opensea-common version +COMMON_MAJOR := 6 +COMMON_MINOR := 0 +COMMON_PATCH := 4 +COMMON_VERSION := $(COMMON_MAJOR).$(COMMON_MINOR).$(COMMON_PATCH) + +# opensea-transport version +TRANSPORT_MAJOR := 10 +TRANSPORT_MINOR := 2 +TRANSPORT_PATCH := 0 +TRANSPORT_VERSION := $(TRANSPORT_MAJOR).$(TRANSPORT_MINOR).$(TRANSPORT_PATCH) + +# opensea-operations version +OPERATIONS_MAJOR := 9 +OPERATIONS_MINOR := 3 +OPERATIONS_PATCH := 0 +OPERATIONS_VERSION := $(OPERATIONS_MAJOR).$(OPERATIONS_MINOR).$(OPERATIONS_PATCH) + +# opensea-jsonformat version +JSONFORMAT_MAJOR := 1 +JSONFORMAT_MINOR := 0 +JSONFORMAT_PATCH := 0 +JSONFORMAT_VERSION := $(JSONFORMAT_MAJOR).$(JSONFORMAT_MINOR).$(JSONFORMAT_PATCH) + +#=============================================================================== +# Project Version +#=============================================================================== + +# Try to get version from git +GIT_VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "unknown") +PROJECT_VERSION ?= $(GIT_VERSION) + +#=============================================================================== +# Verbose Build Support +#=============================================================================== + +# V=1 for verbose output (default to quiet) +V ?= 0 +ifeq ($(V),1) + Q := + VERBOSE := 1 +else + Q := @ + VERBOSE := 0 +endif + +#=============================================================================== +# Color Output (optional, for better UX) +#=============================================================================== + +# ANSI color codes (only if outputting to terminal) +ifeq ($(shell test -t 1 && echo yes),yes) + COLOR_RESET := \033[0m + COLOR_BOLD := \033[1m + COLOR_RED := \033[31m + COLOR_GREEN := \033[32m + COLOR_YELLOW := \033[33m + COLOR_BLUE := \033[34m + COLOR_CYAN := \033[36m + COLOR_HEADER := \033[1;36m + COLOR_STATUS := \033[1;34m +else + COLOR_RESET := + COLOR_BOLD := + COLOR_RED := + COLOR_GREEN := + COLOR_YELLOW := + COLOR_BLUE := + COLOR_CYAN := + COLOR_HEADER := + COLOR_STATUS := +endif + +# Print macros (for nice output) +define print_info + @printf "$(COLOR_BLUE)INFO:$(COLOR_RESET) %s\n" "$(1)" +endef + +define print_warning + @printf "$(COLOR_YELLOW)WARNING:$(COLOR_RESET) %s\n" "$(1)" +endef + +define print_error + @printf "$(COLOR_RED)ERROR:$(COLOR_RESET) %s\n" $(1) +endef + +define print_success + @printf "$(COLOR_GREEN)SUCCESS:$(COLOR_RESET) %s\n" $(1) +endef + +define print_status + @printf "$(COLOR_STATUS)STATUS:$(COLOR_RESET) %s\n" $(1) +endef + +#=============================================================================== +# Export Variables for Recursive Make +#=============================================================================== + +export PLATFORM +export ARCH +export BUILD_TYPE +export OPTIMIZATION_FLAGS +export BUILD_DEFINES +export IS_DEBUG +export IS_STATIC +export BUILD_JSON +export BUILD_SHARED_LIBS +export USING_MUSL +export BUILD_DIR +export OBJ_DIR +export LIB_DIR +export BIN_DIR +export CC +export CXX +export AR +export RANLIB +export STRIP +export INSTALL +export PROJECT_ROOT +export MAKE_ROOT +export VERBOSE diff --git a/Make/jsonformat.mk b/Make/jsonformat.mk new file mode 100644 index 00000000..a97f049d --- /dev/null +++ b/Make/jsonformat.mk @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file jsonformat.mk +# \brief JSON-C and opensea-jsonformat library build (optional, BUILD_JSON=1) + +#=============================================================================== +# JSON-C Library Build (External Dependency) +#=============================================================================== + +# JSON-C build directory +JSONC_BUILD_DIR := $(JSONC_DIR)/build + +# JSON-C library output +LIBJSONC := $(JSONC_BUILD_DIR)/libjson-c.a + +# Build JSON-C using CMake via buildjsonc.sh script +$(LIBJSONC): + @echo "Building JSON-C library via CMake..." + @cd $(JSONFORMAT_DIR)/Make && ./buildjsonc.sh build $(CC) + @echo "JSON-C library built: $(LIBJSONC)" + +.PHONY: json-c +json-c: $(LIBJSONC) + +#=============================================================================== +# opensea-jsonformat Sources +#=============================================================================== + +JSONFORMAT_SOURCES := \ + common_format.c \ + device_format.c \ + farm_format.c \ + log_format.c \ + odata_format.c + +#=============================================================================== +# opensea-jsonformat Include Directories +#=============================================================================== + +JSONFORMAT_INCLUDES := \ + -I$(JSONFORMAT_DIR)/include \ + -I$(OPERATIONS_DIR)/include \ + -I$(TRANSPORT_DIR)/include \ + -I$(COMMON_DIR)/include \ + -I$(JSONC_DIR) \ + -I$(JSONC_BUILD_DIR) + +JSONFORMAT_CFLAGS := $(CFLAGS) +JSONFORMAT_CFLAGS += $(JSONFORMAT_INCLUDES) + +#=============================================================================== +# opensea-jsonformat Object Files +#=============================================================================== + +JSONFORMAT_OBJS := $(addprefix $(OBJ_DIR_JSONFORMAT)/,$(JSONFORMAT_SOURCES:.c=.o)) +JSONFORMAT_DEPS := $(JSONFORMAT_OBJS:.o=.d) + +#=============================================================================== +# opensea-jsonformat Library Targets +#=============================================================================== + +# Static library +LIBJSONFORMAT := $(LIB_DIR)/libopensea-jsonformat.a + +# Shared library (optional) +ifeq ($(BUILD_SHARED_LIBS),1) + LIBJSONFORMAT_SO := $(LIB_DIR)/libopensea-jsonformat.so.$(JSONFORMAT_VERSION) + LIBJSONFORMAT_SO_LINK := $(LIB_DIR)/libopensea-jsonformat.so +endif + +#=============================================================================== +# Build Rules +#=============================================================================== + +# Static library (depends on JSON-C and opensea-operations) +$(LIBJSONFORMAT): $(JSONFORMAT_OBJS) $(LIBJSONC) $(LIBOPERATIONS) | $(LIB_DIR) + $(AR_MSG) + $(Q)$(AR) rcs $@ $(JSONFORMAT_OBJS) + $(Q)$(RANLIB) $@ + +# Shared library (optional) +ifeq ($(BUILD_SHARED_LIBS),1) +$(LIBJSONFORMAT_SO): $(JSONFORMAT_OBJS) $(LIBJSONC) $(LIBOPERATIONS) | $(LIB_DIR) + $(LINK_MSG) + $(Q)$(CC) -shared $(LDFLAGS) -o $@ $(JSONFORMAT_OBJS) \ + -L$(LIB_DIR) -lopensea-operations -lopensea-transport -lopensea-common \ + $(LIBJSONC) -Wl,-soname,libopensea-jsonformat.so.$(JSONFORMAT_MAJOR) + $(Q)cd $(LIB_DIR) && ln -sf libopensea-jsonformat.so.$(JSONFORMAT_VERSION) libopensea-jsonformat.so.$(JSONFORMAT_MAJOR) + $(Q)cd $(LIB_DIR) && ln -sf libopensea-jsonformat.so.$(JSONFORMAT_MAJOR) libopensea-jsonformat.so +endif + +#=============================================================================== +# Phony Targets +#=============================================================================== + +.PHONY: opensea-jsonformat + +# Build jsonformat library (depends on operations, which depends on transport and common) +opensea-jsonformat: opensea-operations $(LIBJSONFORMAT) +ifeq ($(BUILD_SHARED_LIBS),1) +opensea-jsonformat: $(LIBJSONFORMAT_SO) +endif + +#=============================================================================== +# Automatic Dependency Inclusion (.d files) +#=============================================================================== + +# When cross-compiling with MinGW, fix Windows paths in existing .d files BEFORE including them +ifeq ($(CROSS_COMPILING),1) + $(shell find $(OBJ_DIR_JSONFORMAT) -name '*.d' -exec sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' {} + 2>/dev/null || true) +endif + +# .d files are post-processed during compilation to fix Windows paths on cross-compile +-include $(JSONFORMAT_DEPS) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export JSONFORMAT_SOURCES +export JSONFORMAT_INCLUDES +export JSONFORMAT_CFLAGS +export JSONFORMAT_OBJS +export JSONFORMAT_DEPS +export LIBJSONFORMAT +export LIBJSONFORMAT_SO +export LIBJSONC diff --git a/Make/library.mk b/Make/library.mk new file mode 100644 index 00000000..e69aca7b --- /dev/null +++ b/Make/library.mk @@ -0,0 +1,140 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file library.mk +# \brief Library build rules with proper dependency chains for parallel builds + +#=============================================================================== +# Library Source Files +#=============================================================================== + +# Include source lists from subprojects (single source of truth) +include $(COMMON_DIR)/sources.mk +include $(TRANSPORT_DIR)/sources.mk +include $(OPERATIONS_DIR)/sources.mk + +#=============================================================================== +# Include Directories +#=============================================================================== + +COMMON_INCLUDES := -I$(COMMON_DIR)/include +TRANSPORT_INCLUDES := -I$(TRANSPORT_DIR)/include -I$(COMMON_DIR)/include +OPERATIONS_INCLUDES := -I$(OPERATIONS_DIR)/include -I$(TRANSPORT_DIR)/include -I$(COMMON_DIR)/include + +# Add to CFLAGS per library +COMMON_CFLAGS += $(COMMON_INCLUDES) +TRANSPORT_CFLAGS += $(TRANSPORT_INCLUDES) +OPERATIONS_CFLAGS += $(OPERATIONS_INCLUDES) + +#=============================================================================== +# Object File Lists +#=============================================================================== + +COMMON_OBJS := $(addprefix $(OBJ_DIR_COMMON)/,$(COMMON_SOURCES:.c=.o)) +TRANSPORT_OBJS := $(addprefix $(OBJ_DIR_TRANSPORT)/,$(TRANSPORT_SOURCES:.c=.o)) +OPERATIONS_OBJS := $(addprefix $(OBJ_DIR_OPERATIONS)/,$(OPERATIONS_SOURCES:.c=.o)) + +# Dependency files (.d) - automatically generated by -MMD -MP +COMMON_DEPS := $(COMMON_OBJS:.o=.d) +TRANSPORT_DEPS := $(TRANSPORT_OBJS:.o=.d) +OPERATIONS_DEPS := $(OPERATIONS_OBJS:.o=.d) + +#=============================================================================== +# Library Targets +#=============================================================================== + +# Static libraries (.a) +LIBCOMMON_STATIC := $(LIB_DIR)/libopensea-common.a +LIBTRANSPORT_STATIC := $(LIB_DIR)/libopensea-transport.a +LIBOPERATIONS_STATIC := $(LIB_DIR)/libopensea-operations.a + +# Shared libraries (.so) - optional +LIBCOMMON_SHARED := $(LIB_DIR)/libopensea-common.so.$(COMMON_VERSION) +LIBTRANSPORT_SHARED := $(LIB_DIR)/libopensea-transport.so.$(TRANSPORT_VERSION) +LIBOPERATIONS_SHARED := $(LIB_DIR)/libopensea-operations.so.$(OPERATIONS_VERSION) + +# Default library targets (static unless BUILD_SHARED_LIBS=1) +ifeq ($(BUILD_SHARED_LIBS),1) + LIBCOMMON := $(LIBCOMMON_SHARED) + LIBTRANSPORT := $(LIBTRANSPORT_SHARED) + LIBOPERATIONS := $(LIBOPERATIONS_SHARED) +else + LIBCOMMON := $(LIBCOMMON_STATIC) + LIBTRANSPORT := $(LIBTRANSPORT_STATIC) + LIBOPERATIONS := $(LIBOPERATIONS_STATIC) +endif + +#=============================================================================== +# Build Rules with Proper Dependencies +#=============================================================================== + +.PHONY: opensea-common opensea-transport opensea-operations libraries + +# Build all libraries +libraries: opensea-common opensea-transport opensea-operations + +# opensea-common (no dependencies) +opensea-common: $(LIBCOMMON) + +$(LIBCOMMON_STATIC): $(COMMON_OBJS) | $(LIB_DIR) + $(call create_static_lib) + +$(LIBCOMMON_SHARED): $(COMMON_OBJS) | $(LIB_DIR) + $(call create_shared_lib) + +# opensea-transport (depends on opensea-common) +opensea-transport: opensea-common $(LIBTRANSPORT) + +$(LIBTRANSPORT_STATIC): $(TRANSPORT_OBJS) | $(LIB_DIR) + $(call create_static_lib) + +$(LIBTRANSPORT_SHARED): $(TRANSPORT_OBJS) $(LIBCOMMON) | $(LIB_DIR) + $(LINK_MSG) + $(Q)$(CC) -shared $(LDFLAGS) -o $@ $(TRANSPORT_OBJS) -L$(LIB_DIR) -lopensea-common $(PLATFORM_LIBS) + +# opensea-operations (depends on opensea-transport and opensea-common) +opensea-operations: opensea-transport $(LIBOPERATIONS) + +$(LIBOPERATIONS_STATIC): $(OPERATIONS_OBJS) | $(LIB_DIR) + $(call create_static_lib) + +$(LIBOPERATIONS_SHARED): $(OPERATIONS_OBJS) $(LIBTRANSPORT) | $(LIB_DIR) + $(LINK_MSG) + $(Q)$(CC) -shared $(LDFLAGS) -o $@ $(OPERATIONS_OBJS) -L$(LIB_DIR) -lopensea-transport -lopensea-common $(PLATFORM_LIBS) + +#=============================================================================== +# Include Dependency Files (.d files for automatic header tracking) +#=============================================================================== + +# When cross-compiling with MinGW, fix Windows paths in existing .d files BEFORE including them +ifeq ($(CROSS_COMPILING),1) + $(shell find $(OBJ_DIR_COMMON) $(OBJ_DIR_TRANSPORT) $(OBJ_DIR_OPERATIONS) -name '*.d' -exec sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' {} + 2>/dev/null || true) +endif + +# .d files are post-processed during compilation to fix Windows paths on cross-compile +-include $(COMMON_DEPS) +-include $(TRANSPORT_DEPS) +-include $(OPERATIONS_DEPS) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export COMMON_SOURCES +export TRANSPORT_SOURCES +export OPERATIONS_SOURCES +export COMMON_OBJS +export TRANSPORT_OBJS +export OPERATIONS_OBJS +export LIBCOMMON +export LIBTRANSPORT +export LIBOPERATIONS diff --git a/Make/platforms/aix.mk b/Make/platforms/aix.mk new file mode 100644 index 00000000..9be764ac --- /dev/null +++ b/Make/platforms/aix.mk @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/aix.mk +# \brief AIX platform-specific configuration + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_ALL_SOURCE \ + -DDISABLE_NVME_PASSTHROUGH \ + -DDISABLE_TCG_SUPPORT + +# AIX: No NVMe support currently +ENABLE_NVME := 0 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/aix +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# AIX-specific libraries for device management +PLATFORM_LIBS := \ + -lodm \ + -lcfg + +# Standard math library +PLATFORM_LIBS += -lm + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/dragonflybsd.mk b/Make/platforms/dragonflybsd.mk new file mode 100644 index 00000000..a4f6fbae --- /dev/null +++ b/Make/platforms/dragonflybsd.mk @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/dragonflybsd.mk +# \brief DragonFlyBSD platform-specific configuration (uses CAM like FreeBSD) + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_BSD_SOURCE \ + -DENABLE_CAM \ + -DDISABLE_TCG_SUPPORT + +# DragonFlyBSD has NVMe support via CAM (same as FreeBSD) +ENABLE_NVME := 1 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery (reuse FreeBSD CAM helper) +vpath %.c $(TRANSPORT_DIR)/src/freebsd +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# CAM library (required for device access) +PLATFORM_LIBS := -lcam + +# Standard math library +PLATFORM_LIBS += -lm + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/freebsd.mk b/Make/platforms/freebsd.mk new file mode 100644 index 00000000..2b60f835 --- /dev/null +++ b/Make/platforms/freebsd.mk @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/freebsd.mk +# \brief FreeBSD platform-specific configuration (uses CAM for SCSI/ATA/NVMe) + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_BSD_SOURCE \ + -DENABLE_CAM \ + -DDISABLE_TCG_SUPPORT + +# FreeBSD has NVMe support via CAM if the nvme.h header is available +# Check for /usr/include/dev/nvme/nvme.h +FREEBSD_NVME_H := /usr/include/dev/nvme/nvme.h +ifneq ($(shell test -f $(FREEBSD_NVME_H) && printf "yes"),yes) + PLATFORM_DEFINES += -DDISABLE_NVME_PASSTHROUGH + ENABLE_NVME := 0 +else + ENABLE_NVME := 1 +endif + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/freebsd +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# CAM library (required for device access) +PLATFORM_LIBS := -lcam + +# Standard math library +PLATFORM_LIBS += -lm + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/hpux.mk b/Make/platforms/hpux.mk new file mode 100644 index 00000000..3754e5fc --- /dev/null +++ b/Make/platforms/hpux.mk @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/hpux.mk +# \brief HP-UX platform-specific configuration + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_POSIX_C_SOURCE=200112L \ + -D__EXTENSIONS__ \ + -DDISABLE_NVME_PASSTHROUGH \ + -DDISABLE_TCG_SUPPORT + +# HP-UX: No NVMe support currently +ENABLE_NVME := 0 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src +vpath %.c $(COMMON_DIR)/src/posix + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# HP-UX system libraries (if any specific ones are needed) +PLATFORM_LIBS := + +# Math library (standard) +MATH_LIB := -lm + +# No pthread needed (or may need -lpthread if threading is used) + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Platform-Specific LDFLAGS +#=============================================================================== + +# No special linker flags for HP-UX currently + +#=============================================================================== +# HP-UX Tools Detection +#=============================================================================== + +# openSeaChest utilities to build +ENABLE_OPENSEACHEST_NVME := 0 + +# Note: HP-UX support is limited. Testing recommended before production use. diff --git a/Make/platforms/linux.mk b/Make/platforms/linux.mk new file mode 100644 index 00000000..53b839ce --- /dev/null +++ b/Make/platforms/linux.mk @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/linux.mk +# \brief Linux platform-specific configuration + +#=============================================================================== +# NVMe Support Detection +#=============================================================================== + +# Check for NVMe kernel headers (try multiple locations) +NVME_IOCTL_H := /usr/include/linux/nvme_ioctl.h +NVME_H := /usr/include/linux/nvme.h +UAPI_NVME_H := /usr/include/linux/uapi/nvme.h + +HAS_NVME_IOCTL := $(shell test -f $(NVME_IOCTL_H) && echo yes) +HAS_NVME := $(shell test -f $(NVME_H) && echo yes) +HAS_UAPI_NVME := $(shell test -f $(UAPI_NVME_H) && echo yes) + +# Enable NVMe if any header found +ifneq ($(HAS_NVME_IOCTL)$(HAS_NVME)$(HAS_UAPI_NVME),) + ENABLE_NVME := 1 +else + ENABLE_NVME := 0 +endif + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_GNU_SOURCE \ + -DENABLE_CISS \ + -DENABLE_CSMI \ + -DDISABLE_TCG_SUPPORT + +# Add NVMe define if supported +ifeq ($(ENABLE_NVME),1) + PLATFORM_DEFINES += -DENABLE_NVME +else + PLATFORM_DEFINES += -DDISABLE_NVME_PASSTHROUGH +endif + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +PLATFORM_LIBS := -lm -lrt + +# pthread support (for threading in operations) +PLATFORM_LIBS += -lpthread + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Linker Flags +#=============================================================================== + +# Already set in security-hardening.mk: +# -Wl,--gc-sections +# -Wl,-z,relro,-z,now,-z,noexecstack,-z,nodlopen + +# No additional platform-specific linker flags needed + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/netbsd.mk b/Make/platforms/netbsd.mk new file mode 100644 index 00000000..3a057da0 --- /dev/null +++ b/Make/platforms/netbsd.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/netbsd.mk +# \brief NetBSD platform-specific configuration (limited ATA support) + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_BSD_SOURCE \ + -DDISABLE_TCG_SUPPORT \ + -DDISABLE_NVME_PASSTHROUGH + +# NetBSD: Limited to 28-bit ATA commands only +# No NVMe support +ENABLE_NVME := 0 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/netbsd +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# Standard math library +PLATFORM_LIBS := -lm + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/openbsd.mk b/Make/platforms/openbsd.mk new file mode 100644 index 00000000..d70a227c --- /dev/null +++ b/Make/platforms/openbsd.mk @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/openbsd.mk +# \brief OpenBSD platform-specific configuration (limited ATA support) + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_BSD_SOURCE \ + -DDISABLE_TCG_SUPPORT \ + -DDISABLE_NVME_PASSTHROUGH + +# OpenBSD: Limited to 28-bit ATA commands only +# No NVMe support +ENABLE_NVME := 0 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/openbsd +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# Standard math library +PLATFORM_LIBS := -lm + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/sunos.mk b/Make/platforms/sunos.mk new file mode 100644 index 00000000..c899cf7f --- /dev/null +++ b/Make/platforms/sunos.mk @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/sunos.mk +# \brief Solaris/Illumos platform-specific configuration + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D_POSIX_C_SOURCE=200112L \ + -D__EXTENSIONS__ \ + -DDISABLE_NVME_PASSTHROUGH \ + -DDISABLE_TCG_SUPPORT + +# Solaris/Illumos: No NVMe support currently +ENABLE_NVME := 0 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/solaris +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# Standard math library +PLATFORM_LIBS := -lm + +# Solaris may need socket library for network operations +PLATFORM_LIBS += -lsocket -lnsl + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +#=============================================================================== +# Solaris Linker Flags (different syntax than Linux) +#=============================================================================== + +# Solaris linker uses different syntax for some flags +# Already handled in security-hardening.mk with platform check + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/vmware.mk b/Make/platforms/vmware.mk new file mode 100644 index 00000000..0de38522 --- /dev/null +++ b/Make/platforms/vmware.mk @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/vmware.mk +# \brief VMware ESXi platform-specific configuration + +#=============================================================================== +# Include Shared VMware SDK Detection +#=============================================================================== + +include $(MAKE_ROOT)/vmware/vmware-sdk.inc + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + $(VMW_EXTRA_DEFS) \ + -D_GNU_SOURCE \ + -DDISABLE_TCG_SUPPORT + +# VMware: NVMe passthrough is supported +ENABLE_NVME := 1 + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/linux +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# Math library +PLATFORM_LIBS := -lm + +# VMware management library (set in vmware-sdk.inc based on DEV_NEED_VMKMGMT) + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +# VMware SDK provides its own CFLAGS via userworld-tool.inc +# These will be merged with our flags + +#=============================================================================== +# DEV_APP Configuration (per-target) +#=============================================================================== + +# DEV_APP is set by library.mk (empty) and tools.mk (1) +# This tells VMware's build system whether we're building a library or executable + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/platforms/windows.mk b/Make/platforms/windows.mk new file mode 100644 index 00000000..d2589d67 --- /dev/null +++ b/Make/platforms/windows.mk @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file platforms/windows.mk +# \brief Windows/MinGW platform-specific configuration + +#=============================================================================== +# Platform Defines +#=============================================================================== + +PLATFORM_DEFINES := \ + -D__USE_MINGW_ANSI_STDIO=1 \ + -D_CRT_SECURE_NO_WARNINGS \ + -DENABLE_CISS \ + -DENABLE_CSMI \ + -DDISABLE_TCG_SUPPORT \ + -DSTATIC_OPENSEA_COMMON \ + -DSTATIC_OPENSEA_TRANSPORT \ + -DSTATIC_OPENSEA_OPERATIONS + +# Windows always has NVMe support via STORAGE_PROTOCOL_COMMAND +ENABLE_NVME := 1 +PLATFORM_DEFINES += -DENABLE_NVME + +# Windows-specific: enable openSeaChest_NVMe utility +ENABLE_OPENSEACHEST_NVME := 1 + +# Windows-specific: Intel RST passthrough support +# Can be disabled by setting ENABLE_INTEL_RST=0 +ifndef ENABLE_INTEL_RST + ENABLE_INTEL_RST := 1 +endif +ifeq ($(ENABLE_INTEL_RST),1) + PLATFORM_DEFINES += -DENABLE_INTEL_RST +endif + +# Windows-specific: OpenFabrics NVMe IOCTL support +# Can be disabled by setting ENABLE_OFNVME=0 +ifndef ENABLE_OFNVME + ENABLE_OFNVME := 1 +endif +ifeq ($(ENABLE_OFNVME),1) + PLATFORM_DEFINES += -DENABLE_OFNVME +endif + +#=============================================================================== +# Platform-Specific Sources +#=============================================================================== + +# Source lists are now defined in subproject sources.mk files +# See: subprojects/opensea-common/sources.mk +# subprojects/opensea-transport/sources.mk + +# Add to vpath for source discovery +vpath %.c $(TRANSPORT_DIR)/src/windows +vpath %.c $(TRANSPORT_DIR)/src + +#=============================================================================== +# Platform Libraries +#=============================================================================== + +# Windows system libraries +PLATFORM_LIBS := \ + -lversion \ + -lcfgmgr32 \ + -ladvapi32 \ + -lsetupapi + +# No math library needed on Windows +# No pthread needed (use Windows threads via opensea-common) + +#=============================================================================== +# Executable Extension +#=============================================================================== + +EXE_EXT := .exe + +#=============================================================================== +# Platform-Specific CFLAGS +#=============================================================================== + +COMMON_CFLAGS += $(PLATFORM_DEFINES) +TRANSPORT_CFLAGS += $(PLATFORM_DEFINES) +OPERATIONS_CFLAGS += $(PLATFORM_DEFINES) +TOOLS_CFLAGS += $(PLATFORM_DEFINES) + +# MinGW-specific: ensure proper printf format checking +# (Already added in compiler-flags.mk, but emphasize here) + +#=============================================================================== +# Linker Flags +#=============================================================================== + +# Windows-specific: ensure we link static runtime (if desired) +ifeq ($(IS_STATIC),1) + LDFLAGS += -static -static-libgcc +endif + +# Windows doesn't use RELRO/NX linker flags (uses PE format, not ELF) +# Security hardening on Windows is done via: +# - DEP (Data Execution Prevention) - automatic in modern Windows +# - ASLR (Address Space Layout Randomization) - automatic in modern Windows +# - Control Flow Guard - would need /guard:cf (MSVC) or -mguard=cf (MinGW GCC 10+) + +# Enable Control Flow Guard if supported (MinGW GCC 10+) +ifeq ($(IS_GCC),1) + ifeq ($(GCC_AT_LEAST_10),1) + CFG_SUPPORT := $(call cc_supports,-mguard=cf) + ifneq ($(CFG_SUPPORT),) + LDFLAGS += -mguard=cf + endif + endif +endif + +#=============================================================================== +# Export Variables +#=============================================================================== + +export ENABLE_NVME +export ENABLE_OPENSEACHEST_NVME +export EXE_EXT +export PLATFORM_DEFINES +export PLATFORM_LIBS diff --git a/Make/rules.mk b/Make/rules.mk new file mode 100644 index 00000000..950d7188 --- /dev/null +++ b/Make/rules.mk @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file rules.mk +# \brief Pattern rules with automatic dependency tracking (.d files) + +#=============================================================================== +# Automatic Dependency Tracking (.d files) +#=============================================================================== + +# Add flags to generate .d dependency files alongside .o files +# -MMD: generate dependencies, excluding system headers +# -MP: add phony targets for each header to prevent errors if headers are removed +CFLAGS += -MMD -MP +CXXFLAGS += -MMD -MP + +#=============================================================================== +# VPATH Setup (Source File Discovery) +#=============================================================================== + +# VPATH tells Make where to find source files +# This allows us to build out-of-tree (objects in build/, sources in src/) + +# Common source directories +vpath %.c $(COMMON_DIR)/src +vpath %.c $(TRANSPORT_DIR)/src +vpath %.c $(OPERATIONS_DIR)/src +vpath %.c $(JSONFORMAT_DIR)/src +vpath %.c $(UTILS_DIR) +vpath %.c $(PROJECT_SRC_DIR) + +# Platform-specific source directories (will be added by platform modules) +# vpath %.c $(TRANSPORT_DIR)/src/linux +# vpath %.c $(TRANSPORT_DIR)/src/windows +# etc. + +#=============================================================================== +# Compilation Rules +#=============================================================================== + +# Quiet compilation output (unless V=1) +ifeq ($(VERBOSE),1) + Q := + COMPILE_MSG = + LINK_MSG = + AR_MSG = +else + Q := @ + COMPILE_MSG = @echo " CC $<" + LINK_MSG = @echo " LD $@" + AR_MSG = @echo " AR $@" +endif + +# Pattern rule: Compile .c to .o in object directory +# Automatically generates .d dependency file alongside .o file +# $< = source file, $@ = target file (object) +$(OBJ_DIR_COMMON)/%.o: %.c | $(OBJ_DIR_COMMON) + $(COMPILE_MSG) + $(Q)$(CC) $(CFLAGS) $(COMMON_CFLAGS) -c $< -o $@ + $(Q)if [ "$(CROSS_COMPILING)" = "1" ] && [ -f $(@:.o=.d) ]; then sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' $(@:.o=.d); fi + +$(OBJ_DIR_TRANSPORT)/%.o: %.c | $(OBJ_DIR_TRANSPORT) + $(COMPILE_MSG) + $(Q)$(CC) $(CFLAGS) $(TRANSPORT_CFLAGS) -c $< -o $@ + $(Q)if [ "$(CROSS_COMPILING)" = "1" ] && [ -f $(@:.o=.d) ]; then sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' $(@:.o=.d); fi + +$(OBJ_DIR_OPERATIONS)/%.o: %.c | $(OBJ_DIR_OPERATIONS) + $(COMPILE_MSG) + $(Q)$(CC) $(CFLAGS) $(OPERATIONS_CFLAGS) -c $< -o $@ + $(Q)if [ "$(CROSS_COMPILING)" = "1" ] && [ -f $(@:.o=.d) ]; then sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' $(@:.o=.d); fi + +$(OBJ_DIR_JSONFORMAT)/%.o: %.c | $(OBJ_DIR_JSONFORMAT) + $(COMPILE_MSG) + $(Q)$(CC) $(CFLAGS) $(JSONFORMAT_CFLAGS) -c $< -o $@ + $(Q)if [ "$(CROSS_COMPILING)" = "1" ] && [ -f $(@:.o=.d) ]; then sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' $(@:.o=.d); fi + +$(OBJ_DIR_TOOLS)/%.o: %.c | $(OBJ_DIR_TOOLS) + $(COMPILE_MSG) + $(Q)$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@ + $(Q)if [ "$(CROSS_COMPILING)" = "1" ] && [ -f $(@:.o=.d) ]; then sed -i 's|C:/|/mnt/c/|g; s|D:/|/mnt/d/|g; s|E:/|/mnt/e/|g; s|\\\\|/|g' $(@:.o=.d); fi + +#=============================================================================== +# Linking Rules +#=============================================================================== + +# Static library creation (.a) +# $^ = all prerequisites (object files) +define create_static_lib + $(AR_MSG) + $(Q)$(AR) rcs $@ $^ + $(Q)$(RANLIB) $@ +endef + +# Shared library creation (.so) +define create_shared_lib + $(LINK_MSG) + $(Q)$(CC) -shared $(LDFLAGS) -o $@ $^ $(LIBS) +endef + +# Executable linking +define link_executable + $(LINK_MSG) + $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) +endef + +#=============================================================================== +# Clean Targets +#=============================================================================== + +# Note: clean, clean-all, show-config, and help targets are defined in GNUmakefile +# to avoid "overriding recipe" warnings. Only define pattern rules here. + +.PHONY: clean-% + +# Clean specific library or tool (will be defined by library.mk and tools.mk) +clean-%: + @echo "Cleaning $*..." + $(Q)rm -rf $(OBJ_DIR_$*) + $(Q)rm -f $(LIB_DIR)/libopensea-$*.a + $(Q)rm -f $(LIB_DIR)/libopensea-$*.so* + $(Q)rm -f $(BIN_DIR)/openSeaChest_$* + +#=============================================================================== +# Phony Targets +#=============================================================================== + +# Note: Main targets (all, clean, clean-all, install, uninstall, package, +# show-config, help) are defined in GNUmakefile diff --git a/Make/security-hardening.mk b/Make/security-hardening.mk new file mode 100644 index 00000000..bab52705 --- /dev/null +++ b/Make/security-hardening.mk @@ -0,0 +1,221 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file security-hardening.mk +# \brief OpenSSF security hardening flags from meson.build +# \note Reference: https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++ + +# Define comma variable for use in subst/patsubst (Make doesn't allow literal commas in function calls) +comma := , + +# Only perform security hardening flag checking if we're not cleaning +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + # Skipping security checks during clean targets +else +$(info Testing security hardening flags...) +endif + +#=============================================================================== +# Stack Protection +#=============================================================================== + +# Stack protector (not on Windows due to GCC bug, Solaris needs special handling) +ifeq ($(PLATFORM),windows) + ifeq ($(IS_GCC),1) + # GCC on Windows has a bug with -fstack-clash-protection + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 + # Fixed in GCC 11/12 but still fails in 12.2, so skip it + HARDENING_FLAGS += + else + # Clang on Windows is OK + HARDENING_FLAGS += -fstack-clash-protection + endif +else ifeq ($(PLATFORM),sunos) + # Solaris: only enable stack-protector on Illumos, not vanilla Solaris + ifeq ($(KERNEL),illumos) + HARDENING_FLAGS += -fstack-protector-strong -fstack-clash-protection + endif +else + # All other platforms: full stack protection + HARDENING_FLAGS += -fstack-protector-strong -fstack-clash-protection +endif + +#=============================================================================== +# Architecture-Specific Hardening +#=============================================================================== + +# x86_64: Control-flow protection +ifeq ($(ARCH),x86_64) + ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + ARCH_HARDENING := + else + ARCH_HARDENING := $(call cc_supports,-fcf-protection=full) + endif + ifneq ($(ARCH_HARDENING),) + HARDENING_FLAGS += -fcf-protection=full + endif +endif + +# ARM64/AArch64: Branch protection +ifeq ($(ARCH),aarch64) + ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + ARCH_HARDENING := + else + ARCH_HARDENING := $(call cc_supports,-mbranch-protection=standard) + endif + ifneq ($(ARCH_HARDENING),) + HARDENING_FLAGS += -mbranch-protection=standard + endif +endif + +# PowerPC64: Suppress noisy ABI change warnings (since GCC 5) +ifeq ($(findstring ppc64,$(ARCH)),ppc64) + HARDENING_FLAGS += -Wno-psabi +endif + +#=============================================================================== +# FORTIFY_SOURCE (Runtime Buffer Overflow Detection) +#=============================================================================== + +# Test if _FORTIFY_SOURCE=3 is supported without warnings +# Rocky Linux 8 and some distros already set _FORTIFY_SOURCE=2 by default +# which causes redefinition warnings if we try to set it +FORTIFY_TEST_CODE := \ + '\#include \n\ + int main(void) { return 0; }' + +FORTIFY_LEVEL_3 := $(shell echo -e $(FORTIFY_TEST_CODE) | \ + $(CC) -D_FORTIFY_SOURCE=3 -Werror -x c - -o /dev/null 2>/dev/null && echo yes) + +FORTIFY_LEVEL_2 := $(shell echo -e $(FORTIFY_TEST_CODE) | \ + $(CC) -D_FORTIFY_SOURCE=2 -Werror -x c - -o /dev/null 2>/dev/null && echo yes) + +# Use highest supported FORTIFY_SOURCE level +ifneq ($(FORTIFY_LEVEL_3),) + HARDENING_FLAGS += -D_FORTIFY_SOURCE=3 +else ifneq ($(FORTIFY_LEVEL_2),) + HARDENING_FLAGS += -D_FORTIFY_SOURCE=2 +else + # Fallback to =1 (always supported) + HARDENING_FLAGS += -D_FORTIFY_SOURCE=1 +endif + +#=============================================================================== +# Linker Hardening (Security Flags) +#=============================================================================== + +# Test each linker flag individually - not all linkers support all flags +# OmniOS/Solaris linkers don't support many GNU ld flags +LINKER_HARDENING := + +ifneq ($(PLATFORM),windows) + # RELRO (Relocation Read-Only): prevents GOT overwrite attacks + RELRO_TEST := $(shell echo 'int main(void) { return 0; }' | \ + $(CC) -Wl,-z,relro -x c - -o /dev/null 2>/dev/null && echo yes) + ifneq ($(RELRO_TEST),) + LINKER_HARDENING += -Wl,-z,relro + endif + + # BIND_NOW: resolve all symbols at program startup (prevents lazy binding attacks) + NOW_TEST := $(shell echo 'int main(void) { return 0; }' | \ + $(CC) -Wl,-z,now -x c - -o /dev/null 2>/dev/null && echo yes) + ifneq ($(NOW_TEST),) + LINKER_HARDENING += -Wl,-z,now + endif + + # NX Stack (No-Execute): prevent code execution on stack + NOEXEC_TEST := $(shell echo 'int main(void) { return 0; }' | \ + $(CC) -Wl,-z,noexecstack -x c - -o /dev/null 2>/dev/null && echo yes) + ifneq ($(NOEXEC_TEST),) + LINKER_HARDENING += -Wl,-z,noexecstack + endif + + # Disable dlopen() on the executable (library hardening) + NODLOPEN_TEST := $(shell echo 'int main(void) { return 0; }' | \ + $(CC) -Wl,-z,nodlopen -x c - -o /dev/null 2>/dev/null && echo yes) + ifneq ($(NODLOPEN_TEST),) + LINKER_HARDENING += -Wl,-z,nodlopen + endif +endif + +# Garbage collection of unused sections (security + size reduction) +GC_SECTIONS_TEST := $(shell echo 'int main(void) { return 0; }' | \ + $(CC) -Wl,--gc-sections -x c - -o /dev/null 2>/dev/null && echo yes) +ifneq ($(GC_SECTIONS_TEST),) + LINKER_HARDENING += -Wl,--gc-sections +endif + +# Dead code elimination (compiler flag, linker uses --gc-sections above) +HARDENING_FLAGS += -ffunction-sections -fdata-sections + +#=============================================================================== +# Position Independent Code (PIC/PIE) +#=============================================================================== + +# Test for -fPIC support (needed for static libraries on some platforms like BSD) +# This prevents relocation errors when linking static libraries into executables +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + PIC_SUPPORT := +else + PIC_SUPPORT := $(call cc_supports,-fPIC) +endif +ifneq ($(PIC_SUPPORT),) + # Add -fPIC globally for static library compatibility + HARDENING_FLAGS += -fPIC +endif + +# PIE (Position Independent Executable) for ASLR +# Only apply for executables, not libraries (libraries are PIC by default) +# Test both compiler flag (-fPIE) and linker flag (-pie) support +ifneq ($(filter clean distclean mostlyclean,$(MAKECMDGOALS)),) + PIE_CFLAGS_SUPPORT := + PIE_LDFLAGS_SUPPORT := +else + PIE_CFLAGS_SUPPORT := $(call cc_supports,-fPIE) + PIE_LDFLAGS_SUPPORT := $(shell echo 'int main(void) { return 0; }' | \ + $(CC) -fPIE -pie -x c - -o /dev/null 2>/dev/null && echo yes) +endif + +ifneq ($(PIE_CFLAGS_SUPPORT),) + PIE_CFLAGS := -fPIE +else + PIE_CFLAGS := +endif + +ifneq ($(PIE_LDFLAGS_SUPPORT),) + PIE_LDFLAGS := -pie +else + PIE_LDFLAGS := +endif + +#=============================================================================== +# Combined CFLAGS and LDFLAGS +#=============================================================================== + +# Add hardening to compiler flags +CFLAGS += $(HARDENING_FLAGS) +CXXFLAGS += $(HARDENING_FLAGS) + +# Add hardening to linker flags +LDFLAGS += $(LINKER_HARDENING) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export HARDENING_FLAGS +export LINKER_HARDENING +export PIE_CFLAGS +export PIE_LDFLAGS +export CFLAGS +export CXXFLAGS +export LDFLAGS diff --git a/Make/tools.mk b/Make/tools.mk new file mode 100644 index 00000000..a07cdb3e --- /dev/null +++ b/Make/tools.mk @@ -0,0 +1,212 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Do NOT modify or remove this copyright and license +# +# Copyright (c) 2026-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved +# +# This software is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# ****************************************************************************************** +# +# \file tools.mk +# \brief openSeaChest utility builds (17 tools) + +#=============================================================================== +# Common Tool Sources +#=============================================================================== + +# Shared across all tools +TOOL_COMMON_SOURCES := \ + EULA.c \ + openseachest_util_options.c + +#=============================================================================== +# Tool List (Platform-Conditional) +#=============================================================================== + +# All tools except openSeaChest_NVMe (Windows-only) +TOOLS := \ + openSeaChest_Basics \ + openSeaChest_Configure \ + openSeaChest_Defect \ + openSeaChest_Erase \ + openSeaChest_Firmware \ + openSeaChest_Format \ + openSeaChest_GenericTests \ + openSeaChest_Info \ + openSeaChest_Logs \ + openSeaChest_PassthroughTest \ + openSeaChest_PowerControl \ + openSeaChest_Raw \ + openSeaChest_Reservations \ + openSeaChest_Security \ + openSeaChest_SMART \ + openSeaChest_ZBD + +# Add openSeaChest_NVMe on Windows only +ifdef ENABLE_OPENSEACHEST_NVME + TOOLS += openSeaChest_NVMe +endif + +# Tool executables with platform extension +TOOL_EXES := $(addsuffix $(EXE_EXT),$(addprefix $(BIN_DIR)/,$(TOOLS))) + +#=============================================================================== +# Tool-Specific Source Files +#=============================================================================== + +# Each tool has its own main source file +BASICS_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Basics.c +CONFIGURE_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Configure.c +DEFECT_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Defect.c +ERASE_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Erase.c +FIRMWARE_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Firmware.c +FORMAT_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Format.c +GENERICTESTS_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_GenericTests.c +INFO_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Info.c +LOGS_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Logs.c +NVME_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_NVMe.c +PASSTHROUGHTEST_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_PassthroughTest.c +POWERCONTROL_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_PowerControl.c +RAW_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Raw.c +RESERVATIONS_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Reservations.c +SECURITY_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_Security.c +SMART_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_SMART.c +ZBD_SOURCES := $(TOOL_COMMON_SOURCES) openSeaChest_ZBD.c + +#=============================================================================== +# Tool Include Directories and Flags +#=============================================================================== + +TOOLS_INCLUDES := \ + -I$(PROJECT_ROOT)/include \ + -I$(PROJECT_SRC_DIR) \ + -I$(OPERATIONS_DIR)/include \ + -I$(TRANSPORT_DIR)/include \ + -I$(COMMON_DIR)/include + +TOOLS_CFLAGS += $(TOOLS_INCLUDES) + +# Add JSON includes if enabled +ifeq ($(BUILD_JSON),1) + TOOLS_CFLAGS += -I$(JSONFORMAT_DIR)/include -I$(JSONC_DIR) +endif + +#=============================================================================== +# Tool Libraries to Link +#=============================================================================== + +TOOLS_LIBS := -L$(LIB_DIR) -lopensea-operations -lopensea-transport -lopensea-common + +# Add platform libraries +TOOLS_LIBS += $(PLATFORM_LIBS) + +# Add JSON library if enabled +ifeq ($(BUILD_JSON),1) + TOOLS_LIBS += -lopensea-jsonformat -ljson-c +endif + +# Add PIE flags for executables (ASLR security) +TOOLS_CFLAGS += $(PIE_CFLAGS) +TOOLS_LDFLAGS := $(LDFLAGS) $(PIE_LDFLAGS) + +#=============================================================================== +# vpath for Tool Sources +#=============================================================================== + +vpath %.c $(UTILS_DIR) +vpath %.c $(PROJECT_SRC_DIR) + +#=============================================================================== +# Build Rules for Each Tool +#=============================================================================== + +.PHONY: tools $(TOOLS) + +# Build all tools (depends on libraries) +tools: libraries $(TOOL_EXES) + +# Individual tool targets +$(TOOLS): %: $(BIN_DIR)/%$(EXE_EXT) + +# Pattern rule for building tools +# All tools depend on opensea-operations (which transitively brings in transport and common) +$(BIN_DIR)/openSeaChest_Basics$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(BASICS_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Configure$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(CONFIGURE_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Defect$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(DEFECT_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Erase$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(ERASE_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Firmware$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(FIRMWARE_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Format$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(FORMAT_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_GenericTests$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(GENERICTESTS_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Info$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(INFO_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Logs$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(LOGS_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_NVMe$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(NVME_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_PassthroughTest$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(PASSTHROUGHTEST_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_PowerControl$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(POWERCONTROL_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Raw$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(RAW_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Reservations$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(RESERVATIONS_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_Security$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(SECURITY_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_SMART$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(SMART_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +$(BIN_DIR)/openSeaChest_ZBD$(EXE_EXT): $(addprefix $(OBJ_DIR_TOOLS)/,$(ZBD_SOURCES:.c=.o)) $(LIBOPERATIONS) $(LIBTRANSPORT) $(LIBCOMMON) | $(BIN_DIR) + $(LINK_MSG) + $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ $(TOOLS_LIBS) + +#=============================================================================== +# Export Variables +#=============================================================================== + +export TOOLS +export TOOL_EXES +export TOOLS_CFLAGS +export TOOLS_LIBS +export TOOLS_LDFLAGS diff --git a/meson.build b/meson.build index 68aa0239..feab5152 100644 --- a/meson.build +++ b/meson.build @@ -40,6 +40,7 @@ if c.get_id().contains('gcc') or c.get_id().contains('clang') '-Wduplicated-cond', '-Wjump-misses-init', '-Wstringop-overflow', + '-Wstringop-overread', '-Wlogical-op', '-Wshift-overflow', '-Wshift-overflow=1', diff --git a/meson_options.txt b/meson_options.txt index 1faf3e39..d01bc6e7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -17,15 +17,13 @@ option('tools', type : 'array', choices : [ 'Security', 'SMART', 'ZBD' -]) +], description : 'Select which openSeaChest tools to build. (All by default)') + option('tcg', type : 'feature', value : 'disabled') -option('libc_musl', type : 'boolean', value : false) -#openSeaChest_Security can set the password, however this is not enabled by default +option('libc_musl', type : 'boolean', value : false, description : 'Build openSeaChest with musl libc instead of the system default libc (e.g., glibc on Linux). This updates the --license output when linking against MUSL.') + option('json_outputformat', type : 'boolean', value : true, description : 'Enable JSON output format for openSeaChest. Not all outputs are supported yet, but this is a start for the most popular options to output JSON formatted data to the screen.') -#because enabling it may make the system unable to boot, the drive may not show up -#in the OS if it DOES boot or if the drive it hotplugged in, or it may not be possible -#for the user to enter the password they have set because the system, BIOS, or HBA has -#sent the ATA security freeze-lock command to the drive. -#if you really want to enable this option, you can do it, but you have been warned! -option('atasecsetpass', type : 'feature', value : 'disabled') + +option('atasecsetpass', type : 'feature', value : 'disabled', description : 'Enable or Disable ATA Security Set Password support in openSeaChest_Security tool (Disabled by default). WARNING: Enabling this option may cause system boot issues or make the drive inaccessible if not handled properly.') + option('cc-suggest-attribute', type : 'boolean', value : false, description : 'Enable warnings where the compiler can suggest various attributes to be applied to functions for optimization and correctness.') diff --git a/subprojects/opensea-common b/subprojects/opensea-common index 7cd73a32..2db95db9 160000 --- a/subprojects/opensea-common +++ b/subprojects/opensea-common @@ -1 +1 @@ -Subproject commit 7cd73a32a50bde31f85978c3ba14cc2d4b56f10f +Subproject commit 2db95db936dc70781a3790bf246e5394b5a18c7c diff --git a/subprojects/opensea-operations b/subprojects/opensea-operations index 7b6ea3d1..e5740eea 160000 --- a/subprojects/opensea-operations +++ b/subprojects/opensea-operations @@ -1 +1 @@ -Subproject commit 7b6ea3d1abe3e0ef239a00d970ddb052335229ae +Subproject commit e5740eea7db60395783be199ccb6fba714fd8f29 diff --git a/subprojects/opensea-transport b/subprojects/opensea-transport index 62ca9db9..a9a3e3d5 160000 --- a/subprojects/opensea-transport +++ b/subprojects/opensea-transport @@ -1 +1 @@ -Subproject commit 62ca9db9753e3928de03d9ab3380f7847c75856f +Subproject commit a9a3e3d518450dc596b3d0147dacedded2dd39d8