cmake-rs
cmake-rs copied to clipboard
Need to add /build/Release with visual studio 2015 update 3
here my build.rs
extern crate cmake;
fn main() {
let dst = cmake::Config::new("librtmp").build_target("rtmp").build();
if cfg!(any(windows)) {
println!("cargo:rustc-link-search=native={}/build/Release", dst.display());
}
else {
println!("cargo:rustc-link-search=native={}/build", dst.display());
}
println!("cargo:rustc-link-lib=static=rtmp");
}
if I don't add "/build/Release". I get the following error
error: could not find native static library `rtmp`, perhaps an -L flag is missing?
but it's work fine with it.
and on linux i need to add /build
It's a bug or I do it wrong ?
my cmake
cmake_minimum_required(VERSION 3.0)
project(librtmp)
add_library(rtmp
STATIC
rtmp.c
log.c
amf.c
hashswf.c
parseurl.c
amf.h
bytes.h
dh.h
dhgroups.h
handshake.h
http.h
log.h
rtmp_sys.h
rtmp.h
)
if(WIN32)
target_link_libraries(rtmp PUBLIC ws2_32)
endif()
target_compile_definitions(rtmp PUBLIC -DNO_CRYPTO)
I will say I've been baffled by this in the past as well. Unfortunately I actually know very little about cmake itself, but it seems like this is expected behavior from the various generators?
It seems that multi-configuration generators like MSVC always create a sub-folder like Debug or Release. I didn't find any way to change that or get the path to the target in CMakeList.txt https://cmake.org/cmake/help/latest/policy/CMP0026.html.
by the way you do let build = dst.join("build");
but you do return dst
so dst.display()
doesn't return the directory to cmake build.
Running into this as well; given that this issue was around for >2 years, I wonder how other people work around this...
I spent a long time scratching my about this, and I've finally figured this out. I think it is best categorized as a "usage error", and not a true bug, though the documentation should certainly describe how to avoid the error.
The problem comes down to whether CMake is properly being asked to "install" the tool, or just "build" it. I'm going to take the rdkafka-sys crate as an example, since that's what I'm most familiar with. Until recently, we were asking CMake to build the rdkafka
target:
https://github.com/fede1024/rust-rdkafka/blob/d159783c0796159497302ea72ede74d6bfd7d297/rdkafka-sys/build.rs#L176
and then telling Rust to go find the library out of the target/debug/build/rdkafka-sys-HASH/out/build/src
folder. Of course, this didn't work with MSVC for the reasons described here, as the compiled artifacts would end up in build/Debug/src
or build/RelWithDebInfo
. We had a patch the tried to append this configuration name as necessary (https://github.com/fede1024/rust-rdkafka/commit/5cd9c033083c871ce4334c3bf5995afd1ab65e44), but it was buggy (https://github.com/fede1024/rust-rdkafka/issues/191).
In general, the approach of trying to figure out where CMake is going to generate files in the build tree is unworkable! CMake is best treated as a black box. While there is a CMake variable called CMAKE_CFG_INTDIR
that tells you about whether this magic Debug
or RelWithDebInfo
directory is going to exist, and if so what its name is, that variable is completely inaccessible outside of a CMake script itself.
The solution is to ask CMake to actually install the project, at which point CMake will make some promises to you. Libraries will go into CMAKE_INSTALL_PREFIX/lib
, headers will go into CMAKE_INSTALL_PREFIX/include
. This crate is already equipped to set CMAKE_INSTALL_PREFIX
to target/debug/build/rdkafka-sys-HASH
, so that things don't actually get installed into, say, /usr/local
, which would obviously be a disaster. Then we just point Rust at OUT_DIR/lib
, where we know the library will exist, regardless of whether the CMake generator used an extra directory in the build path or not:
https://github.com/fede1024/rust-rdkafka/blob/e86996919f6bc37aabe3dc9fa1c99cfa9ba269e4/rdkafka-sys/build.rs#L231
If a particular project is not installing its libraries into CMAKE_INSTALL_PREFIX/lib, that is most definitely a bug in that project's CMake configuration and should be filed as such with the project.
tl;dr if your project is calling .build_target("something other than install")
, it is probably wrong, and using the install target with an appropriately-adjusted rustc-link-search path will likely fix the issue.
I spent a long time scratching my about this, and I've finally figured this out. I think it is best categorized as a "usage error", and not a true bug, though the documentation should certainly describe how to avoid the error.
The problem comes down to whether CMake is properly being asked to "install" the tool, or just "build" it. I'm going to take the rdkafka-sys crate as an example, since that's what I'm most familiar with. Until recently, we were asking CMake to build the
rdkafka
target:https://github.com/fede1024/rust-rdkafka/blob/d159783c0796159497302ea72ede74d6bfd7d297/rdkafka-sys/build.rs#L176
and then telling Rust to go find the library out of the
target/debug/build/rdkafka-sys-HASH/out/build/src
folder. Of course, this didn't work with MSVC for the reasons described here, as the compiled artifacts would end up inbuild/Debug/src
orbuild/RelWithDebInfo
. We had a patch the tried to append this configuration name as necessary (fede1024/rust-rdkafka@5cd9c03), but it was buggy (fede1024/rust-rdkafka#191).In general, the approach of trying to figure out where CMake is going to generate files in the build tree is unworkable! CMake is best treated as a black box. While there is a CMake variable called
CMAKE_CFG_INTDIR
that tells you about whether this magicDebug
orRelWithDebInfo
directory is going to exist, and if so what its name is, that variable is completely inaccessible outside of a CMake script itself.The solution is to ask CMake to actually install the project, at which point CMake will make some promises to you. Libraries will go into
CMAKE_INSTALL_PREFIX/lib
, headers will go intoCMAKE_INSTALL_PREFIX/include
. This crate is already equipped to setCMAKE_INSTALL_PREFIX
totarget/debug/build/rdkafka-sys-HASH
, so that things don't actually get installed into, say,/usr/local
, which would obviously be a disaster. Then we just point Rust atOUT_DIR/lib
, where we know the library will exist, regardless of whether the CMake generator used an extra directory in the build path or not:https://github.com/fede1024/rust-rdkafka/blob/e86996919f6bc37aabe3dc9fa1c99cfa9ba269e4/rdkafka-sys/build.rs#L231
If a particular project is not installing its libraries into CMAKE_INSTALL_PREFIX/lib, that is most definitely a bug in that project's CMake configuration and should be filed as such with the project.
tl;dr if your project is calling
.build_target("something other than install")
, it is probably wrong, and using the install target with an appropriately-adjusted rustc-link-search path will likely fix the issue.
thanks a lot for this explainer. I really think this crate should include an example cmakelists.txt for cmake noobs like me.
Thx @benesch for the hint!
so should you always install, for example static libraries to CMAKE_INSTALL_PREFIX/lib ?
eg. like so, at the end of my cmakelists.txt:
install(TARGETS example_lib
"${CMAKE_INSTALL_PREFIX}/lib")
this seems to work as well:
install(TARGETS example_lib
"./lib")
which one is preferable?
Thanks!!