sgrif / mysqlclient-sys

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

set properly cargo:rustc-link-lib for mariadb #25

Closed p-alik closed 5 months ago

p-alik commented 4 years ago

I run in an issue due mariadb recently, which inclusive a workaround is described on stackoverflow.

This patch of build.rs would solve my issue, but maybe approach of PR #2 is worthwhile.

diff --git a/build.rs b/build.rs
index 6b573bd..10f893e 100644
--- a/build.rs
+++ b/build.rs
@@ -24,13 +24,24 @@ fn main() {
     } else if cfg!(all(windows, target_env="msvc")) {
         println!("cargo:rustc-link-lib=static=mysqlclient");
     } else {
-        println!("cargo:rustc-link-lib=mysqlclient");
+        match mysql_config("--libs") {
+            Some(v) => {
+                if v.contains(" -lmariadb") {
+                    println!("cargo:rustc-link-lib=mariadb");
+                } else {
+                    println!("cargo:rustc-link-lib=mysqlclient");
+                }
+            },
+            None   => println!("nothing")
+        }
+
     }
 }

-fn mysql_config_variable(var_name: &str) -> Option<String> {
+fn mysql_config(option: &str) -> Option<String> {
+    println!("mysql_config {}", option);
     Command::new("mysql_config")
-        .arg(format!("--variable={}", var_name))
+        .arg(option)
         .output()
         .into_iter()
         .filter(|output| output.status.success())
@@ -39,6 +50,10 @@ fn mysql_config_variable(var_name: &str) -> Option<String> {
         .next()
 }

+fn mysql_config_variable(var_name: &str) -> Option<String> {
+    mysql_config(format!("--variable={}", var_name).as_str())
+}
+
 #[cfg(target_env = "msvc")]
 fn try_vcpkg() -> bool {
     vcpkg::find_package("libmysql").is_ok()

full output of mysql_config:

mysql_config 
Usage: /nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/bin/mysql_config [OPTIONS]
Options:
        --cflags         [-I/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/include/mysql -I/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/include/mysql/mysql]
        --include        [-I/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/include/mysql -I/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/include/mysql/mysql]
        --libs           [-L/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/lib/ -lmariadb]
        --libs_r         [-L/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/lib/ -lmariadb]
        --plugindir      [/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/lib/mysql/plugin]
        --socket         [/run/mysqld/mysqld.sock]
        --port           [3306]
        --version        [10.3.18]
        --libmysqld-libs [-L/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/lib/mysql  -lmysqld]
        --variable=VAR   VAR is one of:
                pkgincludedir [/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/include/mysql]
                pkglibdir     [/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/lib/mysql]
                plugindir     [/nix/store/p9qk6grnkmg96bvhyxix70wcb6bak7xx-mariadb-server-10.3.18-dev/lib/mysql/plugin]

For isntance to compile following C code I've to run gcc -Wall mysql-connect.c -lmariadb. Otherwise I get same exception I've faced with Rust.

#include "mysql/mysql.h"
#include "stdio.h"

#define DB_HOST         NULL
#define DB_USER        "root"
#define DB_PASSW       "test"
#define DB_NAME        "test"
#define DB_PORT        0
#define DB_UNIX_SOCKET NULL

int main( void ) {
   MYSQL mysql;
   mysql_init(&mysql);
   if (!mysql_real_connect(&mysql, NULL, DB_USER, DB_PASSW, DB_NAME, DB_PORT, DB_UNIX_SOCKET, 0)) {
      printf("Error: %s\n", mysql_error(&mysql));
   } else {
      printf("Connected to the server: %s\n", mysql_get_server_info(&mysql));
      mysql_close(&mysql);
   }
}
weiznich commented 4 years ago

I'm not sure if it's the right way to allow linking against another library that is not libmysqlclient here, as the mariadb library will probably evolve into a different direction in the future. From that point of view it is probably a better solution to have a distinct crate for mariadb bindings (and also a distinct Connection type in diesel).

That written: I do not have any control over this repository, so I can only write my opinion here.

p-alik commented 4 years ago

@weiznich, according to official MariaDB versus MySQL: Compatibility

MariaDB's client protocol is binary compatible with MySQL's client protocol.

That's the reason more and more Linux/Unix distributions going to replace mysql by mariadb. I hope mysqlclient-sys crate can support both back ends. At least for time being.

weiznich commented 4 years ago

To be a bit overcautious here: Stating that the client protocol is binary compatible with the MySQL client protocol does not necessarily mean that API provided by the library implementing the client protocol is compatible. For example the changes mentioned in https://github.com/diesel-rs/diesel/issues/2373 are not available in the mariadb API yet as far as I'm aware. (That doesn't necessarily make the mariadb client lib incompatible with the mysqlclient lib, just to point out that there are differences.) (That all does not necessarily mean we should not do this change, only that we should think about potential breakage.)

That said: I think something diesel should focus on after releasing 2.0 is replacing libpq (the postgres client lib) and libmysqlclient with native rust implementation as this would remove much of the linking issues that are constantly brought up at the issue tracker. (For the postgres side there is already https://github.com/diesel-rs/diesel/pull/2257, I think a similar implementation is also possible for mysql based on the mysql crate.

weiznich commented 5 months ago

Implemented in #40