Set C++ object file output location with CMake - c++

I would like to use CMake for a project, but I have the following two requirements:
The final output of the project should be a set of object files (*.o).
The location of the object files is important. I want to select which directory the files are outputted.
Does CMake support this type of behavior? If so, how? Can I do it with move commands after the object file is build?

First create an object library.
Now the problem is that:
Object libraries cannot be imported, exported, installed, or linked.
http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:add_library
I would try to use the install(DIRECTORY ...).
Using the options:
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} #Probably you have to check more precisely where the object files are built
DESTINATION #it's something relative to DESTDIR, if set, or CMAKE_INSTALL_PREFIX otherwise
FILES_MATCHING
PATTERN "*.o"
A flaw of this solution will be in the output directory name, that will be basically decided by cmake, I wonder if anything can be done in that respect.

Related

how to use pb.cc to make libraries in subdirectories, i got "Cannot find source file"

I tries to use FOREACH to generated several pb files. And make two list names PROTO_SRCS & PROTO_HDRS like below.
I can use it in the main CMakeLists. Like add_executable(a SHARED ${PROTO_SRCS} main.cpp).
But I can not use this param in subdirectories to make a library. when I type "cmake .." in main CMakelists build dir. It shown that "Cannot find source file: a.pb.cc".
main CMakeLists.txt
add_library(xxx SHARED ${PROTO_SRCS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/back back)
in src/back CMakeLists.txt
add_executable(yyy ${PROTO_SRCS})
and I can use message to show ${PROTO_SRCS} in subdir so it pass into successfully.
Please help me to point out the problem. Thx a lot
The issue is that in CMake versions older than 3.20 the GENERATED property of source files is only visible in the directory where it is set. Thus, when you add the protobuf-generated source files to a target defined in a different directory, CMake will no longer know that these are files generated during the build. Consequently, CMake will try to locate these files at configuration time, when they obviously do not exist yet.
Unfortunately, at the time of writing there is only a release candidate for CMake 3.20 and no official release yet. So depending on whether you need to coordinate with other coworkers or whether you're working on this project on your own it might not be feasible to use the release candidate.
If you can't use it, the alternative is to create an object library via add_library(protobuf_objs OBJECT ${PROTO_SRCS}) in the directory where you generate the files and to use target_sources(xxx PRIVATE $<TARGET_OBJECTS:protobuf_objs>) and target_sources(yyy PRIVATE $<TARGET_OBJECTS:protobuf_objs>) instead of adding the ${PROTO_SRCS} as source files to these targets directly.

Custom CMake target that uses only CMake functions [duplicate]

I have a project under CMake with some files generated with python generator from XML files. I cannot specify all files generated by this generator in CMakeLists.txt so I use file globbing for this.
The problem is that when I update my XML files or generator sources (which are in the same repository) I would like to have my build system reconfigured so changed files are taken into account when rebuilding the code (via make for example).
Is it possible to make CMake treat some files like it treats CMakeLists.txt files and to make it regenerate build system when those file are changed?
It doesn't require any kind of workarounds. The standard way is to use CMAKE_CONFIGURE_DEPENDS property:
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS <filename>)
Yes, you should be able to do that by (ab)using configure_file(). Configuring a file makes the source a dependency of the CMake run, so that any changes in it cause a reconfiguration. Simply like this:
configure_file(MyInputFile.xml DummyOutput.xml)
Since it has been a while I will add to #roolebo's answer.
There's actually a better command to add a dependency on a file:
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS <relative_or_full_path_to_file>)
What might be confusing is that this command adds a property to the current directory. Well, it does not matter since you can set a full path to a file that resides outside of the current directory's scope, for instance: ../../config.json

CMake retrieve output path

In my Application the user can click on a "Build" button. This will invoke a file dialogue where the user selects the folder with the CmakeCache. After that I'll invoke the cmake --build command with system(command) and the executeable will be built.
Now I'd like to know the path where the executeable was built. I need to copy files into that path.
I know that the file located at /CMakeCacheFolder/projectname/projectname.dir/Release/projectname.log contains the compiler log with the output path in the last line. But is there some other way?
Output directory of the executable/library target tgt can be obtained with generator expression
$<TARGET_FILE_DIR:tgt>
Because this is a generator expression, it can be used only in limited cases. (CMake documents every command and parameter, for which a generator expression can be used).
If you know, that output directory for the target is set via assigning CMAKE_RUNTIME_OUTPUT_DIRECTORY variable, then you may read either this variable or the target's property RUNTIME_OUTPUT_DIRECTORY. Unlike to the generator expressions, the variable's and the property's values can be used everywhere.
But note, that in case of multi-configuration generators (like Visual Studio), configuration name is appended to the variable's (or property's) value for obtain real output directory.
Not a full answer but too much for a comment:
You can define the output directories for executables, shared objects, and libraries for a project as follows:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
And as you determine where to build you now have a common output directory under a well known path.
The directories could also be given on a configuration basis (Debug/Release/RelWithDebInfo/...) as follows
CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG
CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE
CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO
Hope that helps you further.

clion run cmake on each build

I am not sure if its possible to do this with clion, I was testing out the program and enjoy using it to write c code because the ctags and etags support is really nice.
I am copying some files over from the cmake source tree to the bin location on each build. While using clion if I update some of the files that I am copying the results aren't updated within clion.
If I instead go back to the terminal and just run the typical cmake steps
cmake ../ && make && bin/./program
that copies the updated files and I am able to see my results.
This is the CMake command that I am using in my build.
FILE(COPY ${CMAKE_CURRENT_SOURCE_DIR}/resources/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/bin/resources/)
I might be able to restructure the cmake command to make it copy every time or it might just be a clion issue. I am unsure and would like to be able to take care of this all from within clion, instead of going back to the terminal to run the cmake command for updates to take effect.
If you want CMake to make some action whenever some file is changed, you should create a rule using add_custom_command and pass file via DEPENDS argument. Note, that only file-level dependencies are supported by CMake, for make dependency on directory you need to list all files in it.
# Collect list of files within directory.
FILES(GLOB files_list RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/resources/
"${CMAKE_CURRENT_SOURCE_DIR}/resources/*")
# This will contain full paths to files in binary directory.
set(binary_files_list)
foreach(file ${files_list})
set(source_file ${CMAKE_CURRENT_SOURCE_DIR}/resources/${file})
set(binary_file ${CMAKE_CURRENT_BINARY_DIR}/bin/resources/${file})
add_custom_command(OUTPUT ${binary_file}
COMMAND cmake -E ${source_file} ${binary_file}
DEPENDS ${source_file})
list(APPEND binary_files_list ${binary_file})
endforeach()
add_custom_target(resources DEPENDS ${binary_files_list})
Note, that in case of adding/removing files you should to run cmake explicitely. That's why hardcoded files list is preferred to GLOBing.

Map include path to different directory

I am looking for a way to tell CMake to make an include directory appear under another name to the compiler.
Let's say I have a project that needs code from a foreign library. This code resides in a directory foreignLib-1.5.0_build123456 in my project's root directory. From time to time I will want to update this library and in this process change the library directory name.
I want to reference this directory as foreignLib in my C++ source files. I want to be able to write
#include "foreignLib/include/lib.h"
and CMake should tell my compiler to translate this to
#include "foreignLib-1.5.0_build123456/include/lib.h"
Now I am wondering:
Does a feature like this exist in CMake?
If yes, how do I use it?
If yes, which compilers are supported?
I'd probably just copy the entire include directory into my build tree and make that available.
A decent way of doing that is to use file(GLOB_RECURSE ...) to gather a list of files in the includes folder, then use configure_file(<input> <output> COPYONLY) to copy them to the build tree.
By using configure_file, the files in the build tree are only replaced as required. This means that re-running CMake won't automatically make these files appear out-of-date to the build tool, hence avoiding an unnecessary recompilation.
set(ForeignLibName foreignLib-1.5.0_build123456)
set(ForeignLibRoot ${CMAKE_SOURCE_DIR}/${ForeignLibName})
file(GLOB_RECURSE IncludeFiles RELATIVE ${ForeignLibRoot} ${ForeignLibRoot}/*)
foreach(IncludeFile ${IncludeFiles})
configure_file(${ForeignLibRoot}/${IncludeFile}
${CMAKE_BINARY_DIR}/${ForeignLibName}/foreignLib/${IncludeFile}
COPYONLY)
endforeach()
include_directories(${CMAKE_BINARY_DIR}/${ForeignLibName})
This should allow you to do:
#include "foreignLib/include/lib.h"
When you update the foreign library, you'd have to ensure that you also updated the CMakeLists.txt so that CMake re-runs the next time you go to build. Updating the CMakeLists.txt should only involve changing the single line set(ForeignLibName ...).
You could have a look at Cmake's configure_file: Rename your source file into yourfile.cpp.in and do
#include ${DIR_TO_LIB}/include/xy.h
In your CMakeLists, you set the variable DIR_TO_LIB somehow (by parsing command line or something) and issue
configure_file(yourfile.cpp.in, yourfile.cpp)
This will yield yourfile.cpp with the correct path set.
This is probably not exactly what you intended, but I think it would work.
As part of the build process generate an include file at a well known location (later on called "boilerplate/foreignLib_lib.h") with the real include path.
your code file:
#include "boilerplate/foreignLib_lib.h"
boilerplate/foreignLib_lib.h:
#include "foreignLib-1.5.0_build123456/include/lib.h"
Use CMake's include_directories statement or add an -I switch to the *_CXX_FLAGS to add the current foreignLib path to your include path.