Merge branch 'windows-build' into 'master'
Improve linking on Windows See merge request mfkl/vlc-rs!1merge-requests/7/merge
commit
21c4cb25f5
|
@ -16,3 +16,6 @@ crate-type = ["rlib"]
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.build-dependencies]
|
||||
vswhom = "0.1.0"
|
||||
|
|
27
README.md
27
README.md
|
@ -1,10 +1,13 @@
|
|||
# vlc-rs [![Build Status](https://travis-ci.org/garkimasera/vlc-rs.svg?branch=master)](https://travis-ci.org/garkimasera/vlc-rs)
|
||||
|
||||
Rust bindings for libVLC media framework.
|
||||
|
||||
## Status
|
||||
|
||||
Many missing functions and wrappers.
|
||||
|
||||
## Use
|
||||
|
||||
Please add the following dependencies to your Cargo.toml.
|
||||
|
||||
```Toml
|
||||
|
@ -20,7 +23,9 @@ git = "https://github.com/garkimasera/vlc-rs.git"
|
|||
```
|
||||
|
||||
## Example
|
||||
|
||||
Play for 10 seconds from a media file.
|
||||
|
||||
```Rust
|
||||
extern crate vlc;
|
||||
use vlc::{Instance, Media, MediaPlayer};
|
||||
|
@ -45,5 +50,27 @@ fn main() {
|
|||
|
||||
Other examples are in the examples directory.
|
||||
|
||||
## Building
|
||||
|
||||
### Windows
|
||||
|
||||
To build `vlc-rs`, you must either build VLC from source or grab one of the pre-built packages from [videolan.org](https://www.videolan.org/vlc/download-windows.html).
|
||||
|
||||
If you're building for `x86_64`, then you should grab the download labelled "Installer for 64bit version".
|
||||
That installer is actually a self-extracting ZIP archive, so we can extract the contents without installing VLC itself.
|
||||
|
||||
If you're building for `x86`, then you should either download labelled "7zip package" or the one labelled "Zip package".
|
||||
|
||||
Once you've downloaded your chosen package, you should extract it some place such that its path contains no spaces.
|
||||
To point `vlc-rs` at your VLC package, you should set an appropriate environment variable:
|
||||
|
||||
- `VLC_LIB_DIR`: Directory of the VLC pacakge, any architecture
|
||||
- `VLC_LIB_DIR_X86` : Directory of the VLC pacakge, `x86`-only
|
||||
- `VLC_LIB_DIR_X86_64` : Directory of the VLC pacakge, `x86_64`-only
|
||||
|
||||
You should also add the package to your `PATH` variable if you intend to run the program.
|
||||
For distribution of an executable program, you should probably copy over the neccessary DLLs, as well as the `plugins` directory.
|
||||
|
||||
## License
|
||||
|
||||
MIT (Examples are licensed under CC0)
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
fn main() {
|
||||
#[cfg(target_os = "windows")]
|
||||
windows::link_vlc();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows {
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
compile_error!("Only x86 and x86_64 are supported at the moment. Adding support for other architectures should be trivial.");
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use vswhom::VsFindResult;
|
||||
|
||||
pub fn link_vlc() {
|
||||
let vlc_path = vlc_path();
|
||||
|
||||
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
|
||||
let vs = VsFindResult::search().expect("Could not locate Visual Studio");
|
||||
let vs_exe_path = PathBuf::from(
|
||||
vs.vs_exe_path
|
||||
.expect("Could not retrieve executable path for Visual Studio"),
|
||||
);
|
||||
|
||||
generate_lib_from_dll(&out_dir, &vs_exe_path, &vlc_path);
|
||||
println!("cargo:rustc-link-search=native={}", out_dir.display());
|
||||
// NOTE: Without this directive, linking fails with:
|
||||
// ```
|
||||
// error LNK2019: unresolved external symbol vsnprintf referenced in function _{MangledSymbolName}
|
||||
// msvcrt.lib(vsnprintf.obj) : error LNK2001: unresolved external symbol vsnprintf
|
||||
// msvcrt.lib(vsnprintf.obj) : error LNK2001: unresolved external symbol _vsnprintf
|
||||
// ```
|
||||
// https://stackoverflow.com/a/34230122
|
||||
println!("cargo:rustc-link-lib=dylib=legacy_stdio_definitions");
|
||||
}
|
||||
|
||||
fn generate_lib_from_dll(out_dir: &Path, vs_exe_path: &Path, vlc_path: &Path) {
|
||||
// https://wiki.videolan.org/GenerateLibFromDll/
|
||||
|
||||
let vs_dumpbin = vs_exe_path.join("dumpbin.exe");
|
||||
let vs_lib = vs_exe_path.join("lib.exe");
|
||||
let vlc_def_path = out_dir.join("libvlc.def");
|
||||
let vlc_import_lib = out_dir.join("vlc.lib");
|
||||
|
||||
let libvlc = vlc_path.join("libvlc.dll");
|
||||
let exports = Command::new(vs_dumpbin)
|
||||
.current_dir(out_dir)
|
||||
.arg("/EXPORTS")
|
||||
.arg(libvlc.display().to_string().trim_end_matches(r"\"))
|
||||
.output()
|
||||
.unwrap();
|
||||
let exports = String::from_utf8(exports.stdout).unwrap();
|
||||
|
||||
let mut vlc_def = String::from("EXPORTS\n");
|
||||
for line in exports.lines() {
|
||||
if let Some(line) = line.get(26..) {
|
||||
if line.starts_with("libvlc_") {
|
||||
vlc_def.push_str(line);
|
||||
vlc_def.push_str("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
fs::write(&vlc_def_path, vlc_def.into_bytes()).unwrap();
|
||||
|
||||
// FIXME: Handle paths with spaces in them.
|
||||
Command::new(vs_lib)
|
||||
.current_dir(out_dir)
|
||||
.arg("/NOLOGO")
|
||||
.args(&[
|
||||
format!(
|
||||
r#"/DEF:{}"#,
|
||||
vlc_def_path.display().to_string().trim_end_matches(r"\")
|
||||
),
|
||||
format!(
|
||||
r#"/OUT:{}"#,
|
||||
vlc_import_lib.display().to_string().trim_end_matches(r"\")
|
||||
),
|
||||
format!(
|
||||
"/MACHINE:{}",
|
||||
match target_arch().as_str() {
|
||||
"x86" => "x86",
|
||||
"x86_64" => "x64",
|
||||
_ => unreachable!(),
|
||||
}
|
||||
),
|
||||
])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn vlc_path() -> PathBuf {
|
||||
#[allow(unused_assignments)]
|
||||
let arch_path: Option<OsString> = match target_arch().as_str() {
|
||||
"x86" => env::var_os("VLC_LIB_DIR_X86"),
|
||||
"x86_64" => env::var_os("VLC_LIB_DIR_X86_64"),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
arch_path
|
||||
.or_else(|| env::var_os("VLC_LIB_DIR"))
|
||||
.map(PathBuf::from)
|
||||
.expect("VLC_LIB_DIR not set")
|
||||
}
|
||||
|
||||
fn target_arch() -> String {
|
||||
env::var("CARGO_CFG_TARGET_ARCH").unwrap()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue