Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need to add /build/Release with visual studio 2015 update 3 #18

Open
Stargateur opened this issue Oct 26, 2016 · 6 comments
Open

Need to add /build/Release with visual studio 2015 update 3 #18

Stargateur opened this issue Oct 26, 2016 · 6 comments

Comments

@Stargateur
Copy link

Stargateur commented Oct 26, 2016

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)
@alexcrichton
Copy link
Member

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?

@Stargateur
Copy link
Author

Stargateur commented Nov 4, 2016

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.

@RReverser
Copy link

Running into this as well; given that this issue was around for >2 years, I wonder how other people work around this...

@benesch
Copy link

benesch commented Dec 11, 2019

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 (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 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.

yiwu-arbug pushed a commit to tikv/titan that referenced this issue Jan 31, 2020
1. use `#include "port/port.h"` instead of `#include "port/port_posix.h"`
2. added an "install" target for CMake to workaround rust-lang/cmake-rs#18
3. MSVC reported 2 warnings in Titan (and tons of warnings in RocksDB), and these are fixed.
yiwu-arbug pushed a commit to tikv/titan that referenced this issue Feb 19, 2020
1. use `#include "port/port.h"` instead of `#include "port/port_posix.h"`
2. added an "install" target for CMake to workaround rust-lang/cmake-rs#18
3. MSVC reported 2 warnings in Titan (and tons of warnings in RocksDB), and these are fixed.
@anzbert
Copy link

anzbert commented Oct 17, 2022

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 (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 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.

thanks a lot for this explainer. I really think this crate should include an example cmakelists.txt for cmake noobs like me.

@anzbert
Copy link

anzbert commented Oct 17, 2022

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!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants