This may already be answered somewhere, so please point me in the right direction if so - I couldn't find anything that matched my specific problem when googling!
I've got some CppUnit tests that I'm trying to run.
My top-level CMakeLists.txt contains:
include_directories(
${CPPUNIT_INC}
)
link_directories(
${CPPUNIT_LIB}
)
Both of which are set correctly: I print the paths earlier in the CMakeLists.txt file, and they're correct.
In the subfolder, I have;
add_executable(test-lumberjack TestLumberjack.cpp)
target_link_libraries(
test-lumberjack
Lumberjack
CppUnit
${CMAKE_DL_LIBS}
)
INSTALL(TARGETS test-lumberjack DESTINATION ${PROJECT_OUTPUT_TEST_DIR})
ADD_TEST(NAME test-lumberjack COMMAND "${PROJECT_OUTPUT_TEST_DIR}/test-lumberjack")
However, when I run the tests (either by running the file or using ctest -V), I see the usual linker error EDIT: it's not a linker error, see answer below
The library definitely exists, in the path set earlier in the top level CMakeLists.txt.
I'm stumped! I'm assuming there's something key that I'm totally missing, but I haven't a clue what it is. If you'd like more info, let me know and I'll add it.
Cheers.
I'm an idiot: the CppUnit folder wasn't in my library path. Should've realised this when it was crashing at runtime, not during compilation... Doh!
Related
I have project which has not been divided into libraries, but the source is organized in a directory tree. I do not know how to tell cmake to go down a directory, then add the source in that directory to project defined in the parent directory. I have attempted the following:
in project/source/CMakelists.txt:
set(SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/unitTest/main.cpp
)
add_subdirectory("${PROJECT_SOURCE_DIR}/folder1")
add_executable(UnitTestRNG ${SOURCE} ${HEADERS})
then in project/source/folder1/CMakeLists.txt:
set(SOURCE
${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/file1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp
)
set(HEADERS
${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/file1.hpp
${CMAKE_CURRENT_SOURCE_DIR}/file2.hpp
)
using some message() statements, I have found that the the child folder will get the contents of the SOURCE variable, but it's new assignment to that variable will not persist on returning to the parent CMakeLists.txt
Looking for examples and at the cmake tutorial has led me to the conclusion that:
- Source file structures are usually flat within a project
- If code is divided into folders, it is usually is divided into corresponding libraries.
I wonder if there is some "best practice" from which I am deviating by attempting this structure.
Since CMake 3.1 there is a new way to add source from subdirectories: target_sources
Say you have root_dir and root_dir/sub_dir and source files in both. With target_sources you can do this:
In root_dir/CMakeLists.txt define the target
add_library(some_target main.cpp)
add_subdirectory(sub_dir)
In root_dir/sub_dir/CMakeLists.txt add sources:
target_sources(some_target PRIVATE more_cool_stuff.cpp)
some_target will now contain both source files.
It is also possible to use other commands in root_dir/sub_dir/CMakeLists.txt using some_target, for example target_compile_definitions which is quite convenient to add compilation definitions.
I learned about target_sources here, check it out if you want more explanation and examples
Like the second part of arrowdodger's answer says:
in project/source/folder1/CMakeLists.txt:
set(SOURCE
${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/file1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp
PARENT_SCOPE
)
set(HEADERS
${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/file1.hpp
${CMAKE_CURRENT_SOURCE_DIR}/file2.hpp
PARENT_SCOPE
)
Can't you just set all your sources in project/source/CMakelists.txt then?
Anyway, what you need is PARENT_SCOPE or CACHE option on set command.
Preface: I am very new to c and CLion, so apologies in advance if my phrasing is very wrong.
Essentially, I have an assignment that involves two c files (a "main", and one performing a conversion between imperial and metric units). The main c file simply #include-s the conversion file, performs a function within the conversion file, and prints the resulting value to the user. Simple enough, but I keep getting a message every time I try to run it:
"undefined reference to 'conversion'"
I have tried to suss out the problem, and my only idea relates to the banner at the top of conversion.c which says "This file does not belong to any project target, code insight features may not work properly.". I do not understand why I receive this message, because conversion.c and main.c are both within the main project directory, and this setup worked perfectly fine in my previous assignment.
I have searched for solutions online, and the only one that seemed to make sense was to update my CMakeLists.txt file to include add_executable(project conversion.c). This is what my CMakeLists.txt file looks like before I add this line:
cmake_minimum_required(VERSION 3.12)
project(project C)
set(CMAKE_C_STANDARD 11)
add_executable(project main.c)
However, when I add it, I get the error:
CMake Error at CMakeLists.txt:7 (add_executable):
add_executable cannot create target "directory" because another
target with the same name already exists. The existing target is an
executable created in source directory
"/home/john_s/CLionProjects/project". See documentation for
policy CMP0002 for more details.
Presumably this is because the previous line I have (add_executable(project main.c)) is linking to the same directory, but I have no idea how to resolve this. Any suggestions?
From cmake manual:
add_executable(< name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
Adds an executable target called to be built from the source files listed in the command invocation. (The source files can be omitted here if they are added later using target_sources().)
So to combile a single executable using two source files, you just use:
add_executable(target_name source1.c source2.c)
EDIT: NEVERMIND - I had already successfully fixed this problem by putting a copy of the header where the compiler would find it. However, other build errors in cmake-gui kept referring me to the old error log file with the old build error, making me falsely believe I had not solved the problem.
I will close this question once the seven day bounty period is expired.
I am attempting to create a Windows port of a Linux library that uses pthreads via pthreads-win32, but I am having issues telling CMAKE where to locate pthreads.h. Does anyone know how to direct CMAKE to look to a specific location for pthreads.h? And also for the library file?
Alternately, is there some sort of magical global include directory I could use?
For example , in CMakeLists.txt , you can use INCLUDE_DIRECTORIES to include the path .
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
and you can add the link path of pthread.h with this when you want to link the library :
LINK_DIRECTORIES(directory1 directory2 ...)
TARGET_LINK_LIBRARIES(target library1<debug | optimized> library2...)
In here , it say that you can link with libwinpthread.a
I am trying to use PLplot for visualization in a C project.
However, although the headers and the libraries seem to be correctly included (cmake returns no error), when I try to actually use some PLplot functions, I get errors similar to undefined reference to 'c_plinit' and ld returned 1 exit status
I guess it is a linker problem and it seems like a common problem. However, the stuff I found on google are either not applicable for my case or not detailed enough for a beginner like me.
Note that if I add in the CMakeLists.txt:
message(${PLplot_INCLUDE_DIRS})
message(${PLplot_LIBRARY_DIRS})
message(${PLplot_LIBRARIES})
I get the following output:
/usr/local/include/plplot
/usr/local/lib
/usr/local/lib/libplplotcxxd.so
Please help!
EDIT:
The relevant lines from CMakeLists.txt are as follows:
# The directory with the FindPLplot module
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
FIND_PACKAGE(PLplot REQUIRED)
SET(PLplot_LIBRARIES ${PLplot_LIBRARIES} ${PLplot_cxx_LIBRARY})
INCLUDE_DIRECTORIES(${PLplot_INCLUDE_DIRS})
LINK_DIRECTORIES(${PLplot_LIBRARY_DIRS})
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main ${PLplot_LIBRARIES})
INSTALL(TARGETS main DESTINATION bin)
And then, under a folder called cmake, there is a FindPLplot.cmake module similar to the one here: https://github.com/mrquincle/polychronization/blob/master/cmake/
I was originally following this tutorial: http://www.opengl-tutorial.org/miscellaneous/building-your-own-c-application/
just after about half way down, from where it says "Adding a source file in a project"
I created from this my CMakeLists.txt file as so:
cmake_minimum_required (VERSION 2.6)
project (Cube_Project)
find_package(OpenGL REQUIRED)
add_executable(Cube
main.cpp
)
include_directories(
external/glfw-2.7.6/include/
external/glm-0.9.4.0/
external/glew-1.9.0/include/
.
)
set(ALL_LIBS
${OPENGL_LIBRARY}
GLFW_276
GLEW_190
)
target_link_libraries(Cube
${ALL_LIBS}
)
but when I generate the project, I get this error:
ld: library not found for -lGLFW_276
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any ideas?
I think maybe I'm not using the right names in the set(....) section? My three libs are in a folder called external, which is the top level of the project (i.e. CMakeLists is also here).
I put a zip of the project if anyone wants to take a look at the folder layout of output XCode project structure: http://heather.sh/OpenGL_Project.zip
Thanks,
The library is not in the linker's library search path.
The target_link_libraries command is is very straightforward: It simply passes on all of its arguments to the linker without bothering whether any of those libraries actually exist.
In your case, the GLFW_276 library is missing (and possibly the GLEW_190 as well, since the error occurs before that one is being processed). Make sure the library is actually installed on your system and its filename actually matches the name you use here (eg. libGLFW_276.so).
Once you verify that you have the required file, you need to make sure that the linker is able to find it. If the file is not located in one of the standard directories, use either link_directories to add its location to the search path, or find_library to obtain the full path to the library file, which can then be given to target_link_libraries.