sgrif / mysqlclient-sys

Rust bindings for libmysqlclient
Apache License 2.0
37 stars 32 forks source link

mysqlclient-sys Runtime Error on Windows with MySQL 8.x Binding (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND) #57

Closed germanfica closed 2 months ago

germanfica commented 2 months ago

Summary

While working with the mysqlclient-sys library, I encountered a compilation issue with the bindings for MySQL 8.x on Windows. The error suggests that certain DLLs are missing during the compilation process.

Steps to Reproduce

  1. Set up a Windows 10 Pro environment (22H2, OS build: 19045.4780).
  2. Install Rust (cargo 1.80.1 or newer).
  3. Install MySQL Server version 8.x (specifically tested with 8.4.2 LTS, which failed).
  4. Clone the following repository: mysqlclient_example_rust.
  5. Run cargo clean to clean the target directory, which contains the compiled artifacts (binaries, dependencies, and intermediate build files) of the Rust project.
  6. Run cargo run to compile the project.
extern crate mysqlclient_sys as ffi;
use dotenv::dotenv;
use std::ffi::{CStr, CString};
use std::{env, ptr};

fn main() {
    // Load environment varibles from .env file
    dotenv().ok();

    // Get environment varibles
    let db_host = env::var("DB_HOST").expect("DB_HOST must be set");
    let db_user = env::var("DB_USERNAME").expect("DB_USERNAME must be set");
    let db_pass = env::var("DB_PASSWORD").expect("DB_PASSWORD must be set");
    let db_name = env::var("DB_NAME").expect("DB_NAME must be set");
    let db_port: u32 = env::var("DB_PORT")
        .expect("DB_PORT must be set")
        .parse()
        .expect("DB_PORT must be a number");
    let mysql_lib_dir = env::var("MYSQLCLIENT_LIB_DIR").expect("MYSQLCLIENT_LIB_DIR must be set");
    let mysql_version = env::var("MYSQLCLIENT_VERSION").expect("MYSQLCLIENT_VERSION must be set");

    println!("MYSQLCLIENT_LIB_DIR: {}", mysql_lib_dir);
    println!("MYSQLCLIENT_VERSION: {}", mysql_version);

    unsafe {
        // Init MySQL
        let mysql = ffi::mysql_init(ptr::null_mut());
        if mysql.is_null() {
            eprintln!("\x1b[101;37mError initializing MySQL\x1b[0m");
            return;
        }

        // Connect to the db
        let host = CString::new(db_host).unwrap();
        let user = CString::new(db_user).unwrap();
        let pass = CString::new(db_pass).unwrap();
        let dbname = CString::new(db_name).unwrap();
        let port = db_port;

        if ffi::mysql_real_connect(
            mysql,
            host.as_ptr(),
            user.as_ptr(),
            pass.as_ptr(),
            dbname.as_ptr(),
            port,
            ptr::null(),
            0,
        )
        .is_null()
        {
            eprintln!(
                "\x1b[1;31mError connecting to the database: {}\x1b[0m",
                CStr::from_ptr(ffi::mysql_error(mysql)).to_str().unwrap()
            );
            ffi::mysql_close(mysql);
            return;
        }

        println!("\n\x1b[1;32mSuccessfully connected to the database!\x1b[0m");

        // Close connection
        ffi::mysql_close(mysql);
    }
}

Error Encountered:

error: process didn't exit successfully: `target\debug\mysqlclient_example.exe` (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)

WindowsTerminal_tJwkxZMmCu

Workaround

I opted to use a MySQL version that worked for me, specifically MySQL 8.0.17. This version does not produce the compilation error.

WindowsTerminal_4miitkblVI

Request

I am reporting this issue in hopes that someone with more experience with the mysqlclient-sys library can investigate further. It seems there may be a compatibility issue with the bindings for certain MySQL versions on Windows, particularly with newer versions like 8.4.2 LTS. No comprehensive tests have been conducted to verify this across other environments.

Environment

Additional Information

If anyone has encountered similar issues or has insights into resolving this, I would appreciate the assistance. Thank you for your time and help.

germanfica commented 2 months ago

I fixed the compile error issue! Thanks to Dependency Walker I was able to identify the missing dlls, and I was able to understand that the problem was on my side by not including the LIBCRYPTO-3-X64.DLL and LIBSSL-3-X64.DLL dlls that were in C:\mysql-8.0.36-winx64\bin directory in my windows path.

In later MySQL versions than 8.0.17, if your PATH doesn't include C:\mysql-8.0.36-winx64\bin, the system won't be able to find libcrypto-3-x64.dll and libssl-3-x64.dll, leading to compile error issues (missing DLLs).

Solution to properly setup the environment variables for MySQL in Windows 10

When setting up MySQL Client on Windows, you might encounter issues related to missing dependencies, particularly when working with specific versions of MySQL. Here's a step-by-step guide to ensure everything is configured correctly.

Step 1: Set Up Environment Variables

To resolve issues related to missing DLL files, it's essential to correctly set your environment variables. Here's what you need to do:

  1. Add MySQL Bin Directory to PATH:

    • Navigate to the MySQL bin directory and add it to your PATH environment variable. This directory typically contains the necessary DLL files like libcrypto-3-x64.dll and libssl-3-x64.dll.
    • Example for MySQL version 8.0.36:
      PATH=C:\mysql-8.0.36-winx64\bin
  2. Set Additional MySQL Client Variables:

    • Ensure the following variables are also set in your environment:
      MYSQLCLIENT_LIB_DIR=C:\mysql-8.0.36-winx64\lib
      MYSQLCLIENT_VERSION=8.0.36

Step 2: Identify and Ensure Presence of Critical DLLs

The most important MySQL libraries and DLLs that should be present in your setup include:

If you encounter errors related to missing DLL files, you can use a Dependency Walker tool to identify them and ensure these critical libraries are included.

Step 3: Verify Environment Configuration

After setting the environment variables, double-check that the PATH includes the directory where these DLLs are located. This step is crucial because the absence of the correct PATH configuration can lead to errors when the system tries to locate necessary libraries.

For example, in versions later than MySQL 8.0.17, if your PATH doesn't include C:\mysql-8.0.36-winx64\bin, the system won't be able to find libcrypto-3-x64.dll and libssl-3-x64.dll, leading to compile error issues.

Step 4: Test the Configuration

Once you've updated your environment variables, test your setup by running your application:

cargo clean
cargo run

If everything is configured correctly, the errors should be resolved.

Conclusion

The properly setup environment variables and the presence of critical libraries such as mysqlclient.lib, LIBCRYPTO-3-X64.DLL and LIBSSL-3-X64.DLL are crucial when working with MySQL on Windows. Ensure that all necessary directories are included in your PATH and that any additional variables are set correctly. This will prevent common issues like missing DLLs and help your application run smoothly.

germanfica commented 2 months ago

It is important to add C:\mysql-8.x-winx64\lib directory in windows 10 environment variables Path to ensure libcrypto-3-x64.dll and libssl-3-x64.dll DLLs are included in the compile process. This ensures that the rust compiler will be able to get the dlls it needs to compile correctly. Or you can simply paste the missing dlls in the target folder of your project.

Tested versions on Windows 10:

germanfica commented 2 months ago

I closed the issue as this is a setup error in the user environment.

weiznich commented 2 months ago

Thanks for coming back and reporting that it works now. It just seems like upstream changed some things between these versions.

For future reference:

error: process didn't exit successfully: `target\debug\mysqlclient_example.exe` (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)

This error is always a runtime error, not a compile time error. That often indicates an environment setup issue.