Set up P4 API for Go on Windows

This guide outlines how to set up P4 API for Go 2025.2 on a Windows machine. While there are several approaches to installing P4 API for Go, the steps involved in this guide ensure compatibility between all the apps involved.

Prerequisites

Get the following apps and archives before installing P4 API for Go:

Go language

Install Go version 1.24 or later.

  1. Download Go 1.24 or later from the Go website.

  2. Using the downloaded archive or installer, run through the steps to install Go.

  3. To check if Go has been installed successfullu enter the following into a command line:

    go version

    You should see the following output:

    go version go1.25.1 windows/amd64

Download MSYS2 MINGW64

Use the MSYS2 MINGW64 terminal for building the P4 API for Go on Windows. This provides a complete environment with all the necessary tools, including the GCC compiler used by MinGW64 and support for CGO (which allows Go to interact with C/C++ libraries).

Building everything, such as OpenSSL, the P4 API for C/C++, and your Go program, using MinG64 ensures compatibility and avoids linker errors that can occur when mixing different compilers.

This guide uses MinGW-w64 exclusively to build the required OpenSSL libraries and compile the final executable to test P4 API for Go.

  1. Download the MSYS2 installer from the MSYS2 website.

  2. When installing MSYS2, make a note of where you are installing it. For example: C:\msys64

  3. After installation, go to the Start Menu and open MSYS2 MINGW64. We recommend running the terminal as Administrator.

  4. To update the MINGW64 packages, enter:

    pacman -Syu
  5. To get the MINGW64 GCC compiler, enter:

    pacman -S mingw-w64-x86_64-gcc
  6. To check the GCC compiler has been installed correctly, enter:

    gcc --version

    You should see the following output:

    gcc.exe (Rev8, Built by MSYS2 project) 15.2.0
  7. (Optional) To check that Go can run in MINGW64, enter:

    go version

    You should see the following output:

    go version go1.25.1 windows/amd64

Download P4 API for C/C++

Download the P4 API for C/C++ archive directly from the Perforce portal.

It is important to ensure that the version you download matches:

  • Your system architecture (e.g., 64-bit).

  • Your GCC compiler (MINGW64).

  • The OpenSSL libraries you will build later.

Find your compatible version of P4 API for C/C++ by looking at the filename:

p4api-openssl<SSLVER>-<GCCVER>-<THREAD>_<EH>.zip

Where:

  • <SSLVER> = OpenSSL version

  • <GCCVER> = GCC version

  • <THREAD> = win32 or posix

  • <EH> = seh or sjlj

This means Windows with OpenSSL 3 ,GCC version 8, Win 32 and seh exception handling , requires the following P4 API for C/C++ version: p4api-openssl3_gcc8_win32_seh.zip.

The version of P4 API for C/C++ used in the examples in this guide is p4api-openssl3_gcc8_win32_seh.zip.

Another example, Windows with OpenSSL 3 ,GCC version 8, posix and sjlj exception handling , requires the following P4 API for C/C++ version: p4api-openssl3_gcc8_posix_sjlj.zip.

Additionally, the P4 API for Go version must match the P4 API for C/C++ version to ensure compatibility and avoid build or runtime errors. In this guide, the version of P4 API for Go being installed is 2025.1. This means you must download P4 API for C/C++ found in the r25.1 folder.

The following steps outline how to get P4 API for C/C++ from the Perforce portal.

  1. Go to Perforce archive.

  2. Go to r25.1. This matches the version of P4 API for Go we are installing.

  3. Go to bin.mingw64x64. This contains the 64-bit binaries built for MinGW-w64.

  4. Download p4api-openssl3_gcc8_win32_seh.zip.

    This version of P4 API for C/C++ is built for 64-bit MinGW-w64 using at least GCC 8, supports OpenSSL 3.x, and uses seh exception handling, all of which are compatible with your MSYS2 MINGW64 environment and Go.

    If you download a different version of P4 API for C/C++, it will not be compatible with the MINGW64 compiler
  5. After downloading p4api-openssl3_win32_posix_seh.zip, extract the files.

  6. Move the folder to a known location, for example, C:\p4api

  7. Ensure that all files and subfolders are placed directly inside the C:\p4api directory and not inside an additional subfolder created during extraction. For example, the path to the subfolder lib:

    1. C:\p4api\lib is correct.

    2. C:\p4api\p4api-2025.1.2810567\lib is wrong.

Build OpenSSL libraries

OpenSSL libraries are required because P4Go relies on secure communication with the P4 Server using SSL/TLS. These libraries provide the cryptographic functions and protocols required for that secure connection. Without them, P4 API for Go won’t be able to authenticate or transmit data securely.

Once built, you need to copy the OpenSSL DLLs (in this case libssl-3-x64.dll and libcrypto-3-x64.dll) to the same folder as your future Go executable to ensure Windows can locate and load them at runtime. Without this step, your application may fail to start due to missing dependencies, and encrypted connections will not be possible.

To build the required OpenSSL libraries:

  1. Open MSYS2 MINGW64 as an administrator.

  2. Install the required packages to build the OpenSSL libraries. To get these packages, enter:

    pacman -S --needed base-devel mingw-w64-x86_64-toolchain perl
  3. Use the MINGW64 terminal to download and extract OpenSSL:

    wget https://www.openssl.org/source/openssl-3.5.2.tar.gz
    tar -xvzf openssl-3.5.2.tar.gz
    cd openssl-3.5.2
    

    This navigates you to the openssl-3.5.2 folder.

  4. To configure OpenSSL for MINGW64, run the following command:

    ./Configure mingw64 shared --prefix=/mingw64/openssl-3.5.2

    This sets up OpenSSL to build 64-bit shared libraries (DLLs) using GCC, and installs them to /mingw64/openssl-3.5.2.

    You will see the following when the process is complete.

  5. To compile and install the libraries, run the following:

    make -j$(nproc)
    make install
    

    This builds OpenSSL libraries using all CPU cores and installs the headers, libraries, and DLLs to the specified folder (openssl-3.5.2 folder).

    This step may take between 5 and 30 minutes.
  6. To check that the libraries and headers were installed correctly (specifically libssl-3-x64.dll and libcrypto-3-x64.dll), enter:

    ls /mingw64/openssl-3.5.2/bin/lib{ssl,crypto}-3-*.dll

    If the files are present, you should see the following output:

    /mingw64/openssl-3.5.2/bin/libcrypto-3-x64.dll  
    /mingw64/openssl-3.5.2/bin/libssl-3-x64.dll

Download P4 API for Go

Download P4 API for Go from either:

If you are following the steps for installing P4 API for Go with this guide, you must use git to install P4 API for Go. This is to ensure compatibility with the other apps.

To download P4 API for Go from GitHub:

  1. Open MSYS2 MINGW64 as an administrator.

  2. Enter git clone https://github.com/perforce/p4go.git /c/p4go

This will download and extract P4 API for Go to a folder called p4go.

Configure build flags

Before building P4 API for Go, you need to configure environment variables so Go can locate and link the required headers and libraries. These build flags are as follows:

go env -w CGO_ENABLED=1
go env -w CGO_CPPFLAGS="-I<absolute path to P4 API for C++>/include -DOS_NT -g"
go env -w CGO_LDFLAGS="-L<absolute path to P4 API for C++>/lib -L<OpenSSLPath> -lp4api -lssl -lcrypto -lcrypt32 -lws2_32  -lole32 -lshell32 -luser32 -ladvapi32 -lole32 -pthread -v"

When configuring the build flags, replace:

  • <absolute path to P4 API for C++> with the absolute path to the P4 API for C/C++

  • <OpenSSLPath> with the absolute path to OpenSSL libraries matching the OpenSSL version used to build the P4 API for C/C++

For the example in this guide, run the following the configure the build flags:

go env -w CGO_ENABLED=1
go env -w CGO_CPPFLAGS="-IC:/p4api/include -DOS_NT -g"
go env -w CGO_LDFLAGS="-LC:/p4api/lib -LC:/msys64/mingw64/openssl-3.5.2/lib -lp4api -lssl -lcrypto -lcrypt32 -lws2_32 -lole32 -lshell32 -luser32 -ladvapi32 -pthread -v"

These flags do the following:

  • CGO_ENABLED=1: Enables CGO, allowing Go to call C/C++ code.

  • CGO_CPPFLAGS: Points to the P4 API for C/C++ headers and defines platform-specific flags.

  • CGO_LDFLAGS: Links against the P4 API for C/C++ and OpenSSL libraries, plus required Windows system libraries.

This setup ensures your Go build process can correctly compile and link against the Perforce and OpenSSL components.

Check that build flags have been configured by entering the following:

go env CGO_ENABLED
go env CGO_CPPFLAGS
go env CGO_LDFLAGS

If the flags are configured correctly, you will see the following:

1
-IC:/p4api/include -DOS_NT -g
-LC:/p4api/lib -L/c/msys64/mingw64/openssl-3.5.2/lib -lp4api -lssl -lcrypto -lcrypt32 -lws2_32 -lole32 -lshell32 -luser32 -ladvapi32 -pthread -v
When setting CGO_CPPFLAGS and CGO_LDFLAGS, Go may normalize /c/... paths into C:/.... This is expected in MSYS2 MINGW64 and does not affect the build as long as the directories exist.

(Optional) Check all apps are present and the correct version

Go to Shell script to check P4 API for Go prerequisites and copy the code into a new shell script. Save the script with a clear name, such as check_p4go_env.sh, and run it using MINGW64.

Below is an example of the expected output if everything is configured correctly:

Copy
=== P4Go Environment Check ===
[Go]
  Expected: >= 1.24
  Found:    1.25.1
  Result:   PASS

[GCC]
  Expected: >= 8.0 (GCC 15.2 is compatible)
  Found:    15.2.0
  Result:   PASS

[OpenSSL]
  Expected directory: /mingw64/openssl-3.5.2
  Found directory:    /mingw64/openssl-3.5.2
  DLLs found:         libssl-3-x64.dll, libcrypto-3-x64.dll
  Result:             PASS

[P4API]
  Expected: /c/p4api/include/p4/clientapi.h and /c/p4api/lib
  Found:    P4API headers and lib folder
  Result:   PASS

[P4Go]
  Expected: /c/p4go
  Found:    /c/p4go
  Result:   PASS

[CGO Environment Flags]
  CGO_ENABLED:
    Expected: 1
    Found:    1
    Result:   PASS
  CGO_CPPFLAGS:
    Expected: -IC:/p4api/include -DOS_NT -g
    Found:    -IC:/p4api/include -DOS_NT -g
    Result:   PASS
  CGO_LDFLAGS:
    Expected: -LC:/p4api/lib -LC:/msys64/mingw64/openssl-3.5.2/lib -lp4api -lssl -lcrypto -lcrypt32 -lws2_32 -lole32 -lshell32 -luser32 -ladvapi32 -pthread -v
    Found:    -LC:/p4api/lib -LC:/msys64/mingw64/openssl-3.5.2/lib -lp4api -lssl -lcrypto -lcrypt32 -lws2_32 -lole32 -lshell32 -luser32 -ladvapi32 -pthread -v
    Result:   PASS

=== Check Complete ===

Run P4 API for Go

With everything in place, create a test folder and a simple Go script to connect to a P4 Server.

  1. Create a test folder, for example, C:\p4test

  2. Create a file called main.go. Add the following Go script to this file:

    Copy
    package main

    import (
        "fmt"
        "log"

        "github.com/perforce/p4go"
    )

    func main() {
        client := p4.New()

        client.SetPort("perforce:1234")  // Update with your P4 server address
        client.SetUser("user.name")      // Update withusername for the Perforce connection
        client.SetPassword("password")   // Update with password for authentication
        client.SetClient("workspace")    // Update with the workspace name


        if ok, err := client.Connect(); err != nil || !ok {
            log.Fatalf("Connection failed: %v", err)
        }
        defer client.Disconnect()

        result, err := client.Run("info")
        if err != nil {
            log.Fatalf("Failed to run 'p4 info': %v", err)
        }

        fmt.Println("P4Go is working. 'p4 info' output:")
        for _, r := range result {
            fmt.Println(r)
        }
    }
  3. Initialize the Go module:

    go mod init p4test

  4. Add the P4Go dependency:

    go get github.com/perforce/p4go

  5. Tidy up the module to ensure all dependencies are resolved:

    go mod tidy

  6. Build the script:

    go build -o p4test.exe main.go

    You may see the following build error: warning: 'thread' attribute directive ignored [-Wattributes]

    This comes from debug.h in the P4 API for C/C++ headers and is expected when using GCC. It doesn’t affect functionality and can be safely ignored.

  7. If the build is successful, you will see a file p4test.exe called in C:\p4test.

  8. Run the script:

    ./p4test.exe

    This outputs P4 Server information into terminal that starts with the following:

    Wake me up, P4 you go go! P4Go is working!!!
    'p4 info' output:
    map[ServerID:master-1666 allowFetch:2 allowPush:2 a...

P4 API for Go is now set up on your windows machine. You can now rest for eternity.

Shell script to check P4 API for Go prerequisites

Below is a script that checks your environment before you build P4 API for Go and makes sure everything is the correct version and in place

Save the script with a clear name, such as check_p4go_env.sh, add it to a test folder such as C:\p4test.

Copy and paste the following into your check_p4go_env.sh file.

Copy
#!/usr/bin/env bash

echo "=== P4Go Environment Check ==="

# Expected values
MIN_GO_VERSION="1.24"
MIN_GCC_VERSION="8.0"
EXPECTED_OPENSSL_VERSION="3.5.2"
EXPECTED_CPPFLAGS='-IC:/p4api/include -DOS_NT -g'
EXPECTED_LDFLAGS='-LC:/p4api/lib -LC:/msys64/mingw64/openssl-3.5.2/lib -lp4api -lssl -lcrypto -lcrypt32 -lws2_32 -lole32 -lshell32 -luser32 -ladvapi32 -pthread -v'

# Compare versions
version_ge() {
    # returns true if $1 >= $2
    [ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}

# Check Go
echo "[Go]"
if command -v go &>/dev/null; then
    GO_VER=$(go version | awk '{print $3}' | sed 's/go//')
    echo "  Expected: >= $MIN_GO_VERSION"
    echo "  Found:    $GO_VER"
    if version_ge "$GO_VER" "$MIN_GO_VERSION"; then
        echo "  Result:   PASS"
    else
        echo "  Result:   FAIL"
    fi
else
    echo "  Go not found"
    echo "  Result: FAIL"
fi
echo

# Check GCC
echo "[GCC]"
if command -v gcc &>/dev/null; then
    GCC_VER=$(gcc -dumpversion)
    echo "  Expected: >= $MIN_GCC_VERSION (GCC 15.2 is compatible)"
    echo "  Found:    $GCC_VER"
    if version_ge "$GCC_VER" "$MIN_GCC_VERSION"; then
        echo "  Result:   PASS"
    else
        echo "  Result:   FAIL"
    fi
else
    echo "  GCC not found"
    echo "  Result: FAIL"
fi
echo

# Check OpenSSL
echo "[OpenSSL]"
OPENSSL_DIR="/mingw64/openssl-${EXPECTED_OPENSSL_VERSION}"
echo "  Expected directory: $OPENSSL_DIR"
if [[ -d "$OPENSSL_DIR" ]]; then
    echo "  Found directory:    $OPENSSL_DIR"
    if [[ -f "$OPENSSL_DIR/bin/libssl-3-x64.dll" && -f "$OPENSSL_DIR/bin/libcrypto-3-x64.dll" ]]; then
        echo "  DLLs found:         libssl-3-x64.dll, libcrypto-3-x64.dll"
        echo "  Result:             PASS"
    else
        echo "  DLLs missing"
        echo "  Result:             FAIL"
    fi
else
    echo "  OpenSSL directory not found"
    echo "  Result: FAIL"
fi
echo

# Check P4API
echo "[P4API]"
echo "  Expected: /c/p4api/include/p4/clientapi.h and /c/p4api/lib"
if [[ -f "/c/p4api/include/p4/clientapi.h" && -d "/c/p4api/lib" ]]; then
    echo "  Found:    P4API headers and lib folder"
    echo "  Result:   PASS"
else
    echo "  Missing required files or folders in /c/p4api"
    echo "  Result:   FAIL"
fi
echo

# Check P4Go
echo "[P4Go]"
echo "  Expected: /c/p4go"
if [[ -d "/c/p4go" ]]; then
    echo "  Found:    /c/p4go"
    echo "  Result:   PASS"
else
    echo "  Missing /c/p4go"
    echo "  Result:   FAIL"
fi
echo

# Check CGO flags
echo "[CGO Environment Flags]"
ENABLED=$(go env CGO_ENABLED)
CPPFLAGS=$(go env CGO_CPPFLAGS)
LDFLAGS=$(go env CGO_LDFLAGS)

echo "  CGO_ENABLED:"
echo "    Expected: 1"
echo "    Found:    $ENABLED"
[[ "$ENABLED" == "1" ]] && echo "    Result:   PASS" || echo "    Result:   FAIL"

echo "  CGO_CPPFLAGS:"
echo "    Expected: $EXPECTED_CPPFLAGS"
echo "    Found:    $CPPFLAGS"
[[ "$CPPFLAGS" == "$EXPECTED_CPPFLAGS" ]] && echo "    Result:   PASS" || echo "    Result:   FAIL"

echo "  CGO_LDFLAGS:"
echo "    Expected: $EXPECTED_LDFLAGS"
echo "    Found:    $LDFLAGS"
[[ "$LDFLAGS" == "$EXPECTED_LDFLAGS" ]] && echo "    Result:   PASS" || echo "    Result:   FAIL"

echo
echo "=== Check Complete ==="

Run the script from MSYS2 MINGW64 with the following:

./check_p4go_env.sh