askman
askman

Reputation: 516

Using CMake and not able to run program without getting "LINK : fatal error LNK1104: cannot open file 'src.lib'" error

I'm trying to get my head around CMake and have been testing it out in Visual Studio Code on Windows 10 with a simple project that has a couple of header files and compiles with no issues when done manually. I've run cmake .. successfully from the build folder, but upon running cmake --build . I get the above error in reference to my weight_converter.vcxproj file.

I've done a load of searching online but can't find anything that answers what is going on.

From other results I've seen some suggestions in Visual Studio to add <file>.lib to Project Options -> Linker -> Input -> Additional Dependencies on visual studio, but I'm on visual studio code and can't find a corresponding setting. I've found the .vcxproj file in my project, and although I don't really know what's going on in it, src.lib is written next to the <Link>/<AdditionalDependencies> headings.

This is my main CMakeLists.txt file contents for reference:

#   set minimum CMake version, project name, and C++ standard
cmake_minimum_required(VERSION 3.19.4)
project("weight_converter")

add_subdirectory(src)

add_executable(weight_converter weight_converter.cpp )

target_include_directories("${PROJECT_NAME}" PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src")

file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)    
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin ) 

file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)

target_link_libraries("${PROJECT_NAME}" PUBLIC src)

And this is the CMakeLists.txt file in my src folder:

add_library(imperial_to_metric imperial_to_metric.cpp)
add_library(metric_to_imperial metric_to_imperial.cpp)

This is my project structure if it matters:

├───.vscode
├───bin
│   └───Debug
├───build
│   ├───.cmake
│   │   └───api
│   │       └───v1
│   │           ├───query
│   │           │   └───client-vscode
│   │           └───reply
│   ├───CMakeFiles
│   │   ├───3.19.4
│   │   │   ├───CompilerIdC
│   │   │   │   ├───Debug
│   │   │   │   │   └───CompilerIdC.tlog
│   │   │   │   └───tmp
│   │   │   ├───CompilerIdCXX
│   │   │   │   ├───Debug
│   │   │   │   │   └───CompilerIdCXX.tlog
│   │   │   │   └───tmp
│   │   │   └───x64
│   │   │       └───Debug
│   │   │           └───VCTargetsPath.tlog
│   │   ├───CMakeTmp
│   │   └───fa0880fffde885133f10c0b2cfeb0cbc
│   ├───Debug
│   ├───src
│   │   ├───CMakeFiles
│   │   ├───Debug
│   │   ├───imperial_to_metric.dir
│   │   │   └───Debug
│   │   │       └───imperial.31E5CD06.tlog
│   │   └───metric_to_imperial.dir
│   │       └───Debug
│   │           └───metric_t.0BAA5631.tlog
│   ├───weight_converter.dir
│   │   └───Debug
│   │       └───weight_converter.tlog
│   └───x64
│       └───Debug
│           └───ZERO_CHECK
│               └───ZERO_CHECK.tlog
├───lib
├───src
│   └───CMakeLists.txt
│   └───imperial_to_metric.cpp
│   └───metric_to_imperial.cpp
│   └───imperial_to_metric.h
│   └───metric_to_imperial.h
│
├───CMakeLists.txt
└───weight_converter.cpp

Upvotes: 0

Views: 1396

Answers (1)

mydisplayname
mydisplayname

Reputation: 356

The underlying problem is this:

target_link_libraries("${PROJECT_NAME}" PUBLIC src)

This tells CMake to link to a library named src. However in the src/CMakeLists.txt the libraries are called. imperial_to_metric and metric_to_imperial

add_library(imperial_to_metric imperial_to_metric.cpp)
add_library(metric_to_imperial metric_to_imperial.cpp)

So what one probably wants is

target_link_libraries("${PROJECT_NAME}" PUBLIC imperial_to_metric metric_to_imperial)

A minor nit, but it is often better practice to have the library targets specify the build requirements. So instead of:

target_include_directories("${PROJECT_NAME}" PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/src")

one would have the following in src/CMakeLists.txt

target_include_directories(metric_to_imperial PUBLIC ".")
target_include_directories(imperial_to_metric PUBLIC ".")

This way any consumer of imperial_to_metric gets the needed include directories simply by the target_link_libraries command.

Upvotes: 2

Related Questions