Can one add further source files to an executable once defined? - cmake

Given I have defined an executable with its main source file in a CMakeList.txt file:
ADD_EXECUTABLE(MyExampleApp main.cpp)
Can I add further source files to this executable after this line but in the same or an included CMakeList.txt file?

Use target_sources, available since cmake 3.1
eg.
target_sources(MyExampleApp PRIVATE ${extra_file})
https://cmake.org/cmake/help/v3.1/command/target_sources.html

I think you may use:
add_executable(MyExampleApp main.cpp)
add_library(library STATIC ${ADDITIONAL_SOURCES})
set_target_properties(library PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(MyExampleApp library)

It should be noted that for more recent versions of CMake (> 3.1 I think) one can append files to the SOURCES property on targets.
http://www.cmake.org/cmake/help/v3.3/prop_tgt/SOURCES.html

Related

Add include header generated in configure_file

I have a cmake project with an application and a library. The library has one header file generated with configure_file. The problem is that the application code cannot find the generated header file.
What is the proper way to include the generated header file path to the application -I options? target_link_libraries adds the path, but to the source but not to the binary directory?
Is it possible to add a property to the library when add_library is used so that this property can be used when target_link_libraries is used?
If you have generated your header file with
configure_file(config.h.in config.h #ONLY)
and have your library target already created with
add_library(libtarget ${SOURCE_FILES})
it's simply a call to
target_include_directories(libtarget PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
under the assumption that all commands are given in this order and are located in the same CMakeLists.txt file.

How to disable auto ".lib" attaching when I add the dependencies with cmake?

I want to link the ".obj" file to my project.
Here is my code.
set(EXT_LIBS json_reader.obj json_writer.obj)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${EXT_LIBS})
But as a result I following files have been linked.
json_reader.obj.lib
json_writer.obj.lib
".lib" is automatically attached if it's not *.lib file.
I want next result
json_reader.obj
json_writer.obj
How can I link *.obj files to my project?
They should be included by doing this: ADD_EXECUTABLE(myProgram ${OBJS} <other-sources>) or in your case ADD_EXECUTABLE(myProgram ${EXT_LIBS} <other-sources>)
If you want to link differently for debug and release
if(${CMAKE_BUILD_TYPE} == "Debug")
set(EXT_LIBS json_reader.obj json_writer.obj)
else()
set(EXT_LIBS json_reader_alt.obj json_writer_alt.obj)
endif()
You can add the CMAKE_BUILD_TYPE parameter to cmake-gui by adding the entry.
A .LIB file is a collection of .OBJ files concatenated together with an index. There should be no difference in how the linker treats either.
As per answer
It seems to me that the add_library only works on .a and .lib files.
And TARGET_LINK_LIBRARIES only adds system library files.

add_executable create two binaries files instead of one

protoc.cmake:
set(protoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/main.cc
)
add_executable(protoc ${protoc_files})
target_link_libraries(protoc libprotobuf libprotoc)
add_executable(protobuf::protoc ALIAS protoc)
set(PROTOC_NAME "protoc")
set_target_properties(protoc PROPERTIES
VERSION ${protobuf_VERSION}
OUTPUT_NAME ${PROTOC_NAME})
if(WIN32)
set(PROTOC_SUFFIX ".exe")
set_target_properties(protoc PROPERTIES
SUFFIX ${PROTOC_SUFFIX})
else()
set(PROTOC_SUFFIX)
endif()
set(PROTOBUF_PROTOC_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROTOC_NAME}${PROTOC_SUFFIX}" PARENT_SCOPE)
I have included source of google protocol buffer compiler to my project, and I use previous cmake file for generating runtime binary, but instead of one file I get two executable files: "protoc" and "protoc-3.6.1".
I am using CLion IDE 2018.1.5 with bundled CMake 3.10.3 on Ubuntu 18.04.
On Windows I don't have a such problem.
As #Tsyvarev said in comment, one of these files is actually a symlink to another one. This is what VERSION property implies.

In CLion/CMake on Windows, how does APP.exe find lib/A.dll in order to run?

I have a CLion/CMake project that needs an external DLL, A.dll, which I have placed in the project lib/ directory. After building the executable, when I run the APP.exe, it cannot find/use the lib/A.dll. How do I fix this?
I think you didn't add .dll file to cmake file this is Quick CMake Tutorial
or CLion and CMake: only building a library without an executable?
I usually just add D:/path/to/lib/A.dll to the Path, either globally by editing the user or system environment variables, or by creating a small batch file which sets up the Path along with CMAKE_PREFIX_PATH et al then possibly spawns something like cmake-gui.exe or devenv.exe.
If you are asking import exist lib in cmake,this link can be help.
you may need this code in your CMakeList.txt
# Create an IMPORTED library
add_library(A IMPORTED)
# Set IMPORTED_LOCATION *property* for this target
set_target_properties(SimpleAmqpClient PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/A.dll)
# Then use library *target* for linking with
target_link_libraries(APP PUBLIC A)

Making a CMake library accessible by other CMake packages automatically

I have one project that produces a library:
project (myCoolLibrary)
ADD_LIBRARY(my_cool_library SHARED ${mysources_SRC})
And another project that should be using this library:
find_package (myCoolLibrary REQUIRED)
INCLUDE_DIRECTORIES("${myCoolLibrary_INCLUDE_DIRS}" )
add_executable(myCoolExe ${my_sources_SRC} )
TARGET_LINK_LIBRARIES(myCoolExe ${myCoolLibrary_LIBRARIES} )
Is there a way that I can change the first file so that the second file works automatically? That by running CMake on the first file and then running make on the output, then running CMake on the second file, CMake is able to find the package?
An answer where I just give the address of where the first project is built to the second package is also acceptable.
Taking the code found in a blog post by #daniperez - Use CMake-enabled libraries in your CMake project (III) - I've come up with the following minimal solution:
myCoolLibrary/CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(myCoolLibrary)
function(my_export_target _target _include_dir)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
"
include(\"\$\{CMAKE_CURRENT_LIST_DIR\}/${_target}Targets.cmake\")
set_property(
TARGET ${_target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES \"${_include_dir}\"
)
"
)
export(TARGETS ${_target} FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake")
# NOTE: The following call can pollute your PC's CMake package registry
# See comments/alternatives below
export(PACKAGE ${_target})
endfunction(my_export_target)
...
add_library(${PROJECT_NAME} SHARED ${mysources_SRC})
my_export_target(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}")
myCoolExe/CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(myCoolExe)
find_package(myCoolLibrary REQUIRED)
...
add_executable(${PROJECT_NAME} ${my_sources_SRC})
target_link_libraries(${PROJECT_NAME} myCoolLibrary)
To make it reusable I have packed everything into my_export_target(). And I'm friend of self-propagating properties like INTERFACE_INCLUDE_DIRECTORIES.
As commented by #ruslo, using export(PACKAGE ...) can pollute your package registry. So alternatively you can:
Write the target configuration files directly to some dedicated place specific for a certain toolchain
See e.g. How to install your custom CMake-Find module and 0003659: FIND_PACKAGE command improvements.
Set CMAKE_MODULE_PATH via the second project's CMake command line (injecting the search path(s) from the outside). If you are building the two projects anyway with a build script, then this is the most direct way to propagate the module search path(s).
Additional References
export()
CMake/Tutorials/Package Registry
Unable to find Eigen3 with CMake
How to instruct CMake to use the build architecture compiler