1

I'm developing a c++ program on visual studio that will be deployed on linux, and it is debugged on linux through an ssh. Currently, this is the structure of my folder:

ANT
-xscommon
--xscommon_config.h
-xscontroller
-xstypes
ANT.cpp
ANT.h
CMakeLists.txt
CMakeSettings.json
hashes.h
quaternionic.h
stars.h

Currently, all the .h, .cpp, .o, .cpp.o, .a files that I think I have to link to are kept within the three xs------- directories. I am quite new to cmake, and this linking to these libraries is giving me trouble; I am able to link correctly to the includes, but there are undefined references errors thrown when I don't do linking, and when I attempt linking, it throws errors. This is my current CMakeLists.txt file:

# CMakeList.txt : CMake project for ANT, include source and define
# project specific logic h"ere.
#
cmake_minimum_required (VERSION 3.8)

project ("ANT")

link_directories(${ANT_SOURCE_DIR}/xscommon xscontroller xstypes)

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
    "quaternionic.h" 
    "stars.h"
    "hashes.h"
)

target_include_directories(ANT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(ANT PUBLIC xscommon_config)

When I run this, the builder says the following:

/usr/bin/ld: cannot find -lxscommon_config

I need to look for these libraries in the directory that ANT.cpp is in, as this is where they are kept, however nothing I do (and I have messed around with configurations for hours now) will tell camke to look for these libraries in the src folder. it always goes to /usr/bin/ld.

I really just need to know what to tell CMake such that it will look in the correct place for each file, that is if I am telling it to look for the correct file (I am fairly sure I am).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Update

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

So I have remade the CMakeLists.txt file to this:

# CMakeList.txt : CMake project for ANT, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.15)

project ("ANT")

#[STATIC | SHARED | MODULE]
#[STATIC | SHARED | MODULE]
#[STATIC | SHARED | MODULE]


add_library(xscommon SHARED IMPORTED)
add_library(xscontroller SHARED IMPORTED)
add_library(xstypes SHARED IMPORTED)

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
)

target_include_directories(ANT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

And still get undefined references. I am going to try building the libraries instead. Additionally, I have contacted the manufacturer of the IMUs which use this SDK, as colleagues have not been able to fix this either.

Legayone
  • 33
  • 5
  • Welcome to Stack Overflow! If you're trying to link pre-built external libraries to your `ANT` executable, see [this](https://stackoverflow.com/questions/8774593/cmake-link-to-external-library) question and its responses for proper methods for accomplishing this. – Kevin Jul 13 '20 at 11:33

2 Answers2

1

The problem is you are linking to a library that has not been build. This

# link to this directory
target_link_libraries(ANT PRIVATE xscommon)

tries to link to a library called xscommon to the target ANT but you have not build xscommon anywhere in your project.

If xscommon is a pre-build library and you just want to import it then add the library and set the IMPORTED target property:

add_library(xscommon [STATIC | SHARED | MODULE] IMPORTED)

If you want to build xscommon in your root CMakeLists.txt. Add xscommon as a library and include the location of the headers.

add_library(xscommon [STATIC | SHARED | MODULE]
    xxx/xxx.cpp #list all source files that build the library - use relative path
)
target_include_directories(xscommon PRIVATE
   xxx/xxx #path to the location of library header files
)

Also you don't need to add the header files when adding the executable. So this

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
    "quaternionic.h" 
    "stars.h"
    "hashes.h"
)

can be simplified to

add_executable(
    ANT
    "ANT.cpp" 
)
kereh
  • 41
  • 3
  • I attempted the first option, with without any decent luck, still undefined references. I am attempting the build option. – Legayone Jul 14 '20 at 09:49
0

Suppose your dir is like this:

ANT
-xscommon
--xscommon_config.h
--xscommon_config.cpp
...

First add a CMakeLists.txt file to xscommon/:

ANT
-xscommon
--CMakeLists.txt
--xscommon_config.h
--xscommon_config.cpp
...

Now in xscommon/CMakeLists.txt we will create a library, that will be imported and linked in the main CMakeLists.txt file:

xscommon/CMakeLists.txt:

#define another target, let's name it 'xscommon'
add_library(xscommon
   xscommon_config.h
   xscommon_config.cpp
   #more sources if you want
   )

Now in the main CMakeLists.txt file:

cmake_minimum_required (VERSION 3.8)

project ("ANT")

#remove this line
#link_directories(${ANT_SOURCE_DIR}/xscommon xscontroller xstypes)

add_executable(
    ANT
    "ANT.cpp" 
    "ANT.h" 
    "quaternionic.h" 
    "stars.h"
    "hashes.h"
)

# add the xscommon directory, this will make the library target defined there available here
add_subdirectory(xscommon)

# link to this directory
target_link_libraries(ANT PRIVATE xscommon)
# use PUBLIC if the xscommon library will be part of the public interface of your
# library. But since it is an executable, PRIVATE is better here.

target_include_directories(ANT PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Use the above method, you can create more libraries and link to them.

Note that it is not necessary to create separate cmake files for each subdirectory but it is considered a good practice and modularizes your code. If you want to do this in the main cmake file instead of creating a subdirectory, add this to the main cmake:

add_library(xscommon
   xscommon/xscommon_config.h
   xscommon/xscommon_config.cpp
   #more sources if you want
   )

Update according to the changes in question

Your current CMakeLists.txt:

These three lines below are not doing anything, definitely not what you think. add_library() command has the word "add" in it, I know, but it doesn't add any library, just like add_executable doesn't add any executable. It creates a library.

add_library(xscommon SHARED IMPORTED)
add_library(xscontroller SHARED IMPORTED)
add_library(xstypes SHARED IMPORTED)

How to create a library in cmake out of two file a.cpp and a.h:

add_library(myALib "a.cpp")

That's it. If you have more sources, you will include them accordingly of course. In your case you will have to add the sources of xscommon and others accordingly.

Once you have created the libraries, you need to link them to your executable. If you won't you will get undefined reference errors because compiler can locate the declarations in header files but not the definitions of your code which exists in .cpp files.

So, how do you link? Simple:

target_link_libraries(TARGET_NAME PUBLIC | PRIVATE LIBRARY_NAME)
# TARGET_NAME: can be `executable` or `library`
# PUBLIC or PRIVATE (for exe, it is usually private)
# LIBRARY_NAME: Name of library you want to link to TARGET_NAME

# So if you wanted to link "myALib" which I created above to ANT, you would do:
target_link_libraries(ANT PRIVATE myALib)

# Note: You need to add this line **after** add_executable() because target "ANT" will be created after that. You can do the linking after the "target_include_directories" command.
Waqar
  • 8,558
  • 4
  • 35
  • 43
  • For each of the folders with a new CMakeLists.txt it says this: ``` 1> [CMake] CMake Error: Cannot determine link language for target "ixscommon". 1> [CMake] CMake Error: CMake can not determine linker language for target: xscommon ``` or some variant. It seemingly treats the library name as a link. If I remove link from CMakeLists.txt, it says the same thing, but for xscommon_config.h – Legayone Jul 13 '20 at 09:19
  • do you have `.cpp` files in `xscommon`? If not, then it is futile to make a library out of it. – Waqar Jul 13 '20 at 09:48
  • can you update the question, to add the changes you made (separately), so that I can see what you did exactly? and if possible, maybe show the files that are in `xscommon`? – Waqar Jul 13 '20 at 09:50
  • Will do. I have used the advice from the comment below this, though it does not seem to want to work that way either. – Legayone Jul 14 '20 at 09:45
  • Just saw your updated cmake, that won't work definitely. I will update the answer – Waqar Jul 14 '20 at 18:41
  • I updated the answer assuming you have the source code of `xscommon` and other libs. If they are prebuilt, you just need the last part `target_link_libraries`, where `LIBRARY_NAME` will be the `PATH + lib name`. So, if lib name is `libxscommon.a`, you will write `target_link_libraries(ANT PRIVATE xscommon/xscommon)`. CMake will add `lib` prefix automatically. – Waqar Jul 15 '20 at 06:24