At the moment I believe I need to get the location of a target's output from the command line of Cmake (after it's built).
Or, maybe I need to script CMake to allow a process to be run on a target (after it's built).
Our basic flow will be:
code
build
debug
build
profile
build
etc.
and I want to make this more easily done from one place on the command line.
At the moment, we're planning on putting a python front end to our build stuff (since it's a heterogenous SoC with multiple processors, we can't have a single configuration due to multiple compilers required) so some scripting on the outside isn't a big deal.
I'd like to be able to do something like:
cmake <configuration stuff>
build.py <target>
debug.py <target>
profile.py <target>
without the developer having to know exactly where the target's binary is. (FYI, these things are more complicated than just calling gdb or whatever, so they do require a script to make it happen from the command line via 3rd party tools)
Is this easily accomplishable? Or do I need to script up some stuff in Cmake to output the required information to a file during configuration and query that file after the fact?
Any guidance or help accomplishing my goal is greatly appreciated.
edit: trying to be more pointed in my questioning:
After I've configured using cmake. is there a way from the build directory to run cmake again to query the cache/buildsystem/whatever to find out where a target's output would be.
for example:
./source
/modules
/module1
/submodule1
/test1
/submodule2
/test1
/module2
/test1
/module3
/test1
I go into my build directory, do cmake -S .. -B . <etc>
I now have a tree filled with makefiles and other stuff.
If i do make, that tree gets populated with build artifacts that roughly mirrors the source tree (at least it does in my experience)
if I do make help it outputs a bunch of targets by name.
module1
submodule1
submodule1_test1
submodule2
submodule2_test1
etc.
Now, I want to know where submodule1_test1's executable is without having to know that its parent is module1. Can I, at this point, run cmake and query the cache/buildsystem to get the location of that named target?
If I can't, I can manage it myself by forming a "database" at configure time. It's not a problem. I just was hoping cmake kept that information around for querying at a later time in its cache or whatever.
When you first generate your project with CMake, it creates a CMakeCache.txt file which has all the variables cache variables from your project. You can use Python to parse it and find the project_name_BINARY_DIR variable. That will be your build destination root. From that point on, you can use Python to recursively check the subdirectories for test executables if they all have a standard naming pattern such as FooTests.exe.
Alternatively, if you use the set cache command, it should also get added to the CMakeCache.txt.
Related
I have an embedded project (using ESP-IDF which builds projects with CMake), where I have a props.json file that contains several settings (e.g. "device type"). For example based on the actual value of "deviceType" the CMake open and read props.json by calling execute_process() and jq, then defines C preprocessor macros, such as: DEVICE_TYPE_A by using add_compile_definitions().
The problem is that, this will run only when I modify the CMakeLists.txt or clean the whole project, but I don't want to recompile each components when I change the props.json only the files that I wrote (so, depend on the settings). I'd like to make CMake read the file each time I build the project without cleaning it.
I did my research, so I know there are add_custom_target() and add_custom_command() that behave that way, however add_compile_definitions() cannot be called in a script. Is there a solution to achieve this or should I just use a header file configured by configure_file() and leave add_compile_definitions() alone?
This is actually pretty easy and you don't need to manually reconfigure CMake. Just add the following to the CMakeLists.txt in the directory containing your props.json file:
set_property(DIRECTORY . APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS props.json)
This will add props.json to the list of files that the CMake-generated build scans when determining whether to re-run the CMake configure step. See the docs on CMAKE_CONFIGURE_DEPENDS for more detail.
In general, you should never need to manually re-run CMake1 after the first configure. If you do, it is an indication that you have not communicated all of the necessary information for CMake to generate a correct build system.
1 There is one notable exception: Xcode is known to be buggy when re-running the CMake configure step automatically.
I have an autotools C project that needs to use another library that is built with CMake. Is their an equivalent to AC_CONFIG_SUBDIRS that will work with CMake?
I take it that you want to configure and build the CMake-based project as part of configuring and building the Autotools-based host project. This is possible, and there are several viable ways to do it, but I'm not aware of anything wholly pre-packaged like AC_CONFIG_SUBDIRS is for Autotools-based subprojects.
For configuration
Option 1 - config commands
Autoconf provides a group of macros by which you can specify custom commands for configure or the generated config.status script to run. You could use one of these -- probably AC_CONFIG_COMMANDS, but maybe AC_CONFIG_COMMANDS_POST -- to run cmake (and any wanted preparatory steps) in the subproject. Personally, I like this option best.
Option 2 - glue script
AC_CONFIG_SUBDIRS instructs configure to run configure scripts in the specified subsirectories, but those other configure scripts don't need to be Autotools-generated. You could conceivably write a custom wrapper script named "configure" in the subproject directory for the parent configure to run, but which itself performs an appropriate call to cmake. AC_CONFIG_SUBDIRS in the top-level configuration should then run that script at the right time.
Option 3 - custom code
I think Autoconf already provides sufficient support for what you seem to want, but if you think otherwise then you always have the option of writing whatever shell code you want into configure via configure.ac. You might find it worthwhile to write a custom macro for that, especially if you have multiple CMake subprojects, but that's not obligatory. Note that such commands are distinguished from those specified via AC_CONFIG_COMMANDS & co. by the timing of their execution.
For building
Presumably you'll be relying on recursive make during the build and installation steps. It shouldn't be hard to make that work, whether you're using an Automake-based Makefile.in or a hand-rolled one at the top level.
Option 1 - Automake + glue makefile
Use a SUBDIRS variable in your top-level Makefile.am to direct make to recurse into the CMake project's subdirectory, just as you would do into any other project's. Write a simple Makefile there that recurses into a build subdirectory (which you will have had to ensure is created and configured by configure). This should not collide with the subproject because it presupposes that a separate build directory is used. The glue makefile can adapt targets and make variables to the expectations of the subproject's build system.
The Automake documentation describes all the recursive targets that the top-level Autotools makefile might try to build recursively, and the glue makefile should provide all of them -- though there may be many that need only a dummy (but not empty) recipe.
Option 2 - hand-rolled top-level Makefile.in
If, on the other hand, you're using a hand-rolled top-level Makefile template then you have full control over your recursive make invocations. You could still use a glue makefile in the subproject in this case, but it's probably easier and cleaner to just adapt directly to the expected CMake-generated makefile.
After running the cmake command once to generate a build system, when, if ever, should I rerun the cmake command?
The generated build systems can detect changes in the associated CMakeLists.txt files and behave accordingly. You can see the logic for doing so in generated Makefiles. The exact rules for when this will happen successfully are mysterious to me.
When should I rerun cmake? Does the answer depend on the generator used?
This blog post (under heading: "Invoking CMake multiple times") points out the confusion over this issue and states that the answer is actually 'never', regardless of generator, but I find that surprising. Is it true?
The answer is simple:
The cmake binary of course needs to re-run each time you make changes to any build setting, but you wont need to do it by design; hence "never" is correct regarding commands you have to issue.
The build targets created by cmake automatically include checks for each file subsequently [=starting from the main CMakeLists.txt file] involved or included generating the current set of Makefiles/VS projects/whatever. When invoking make (assuming unix here) this automatically triggers a previous execution of cmake if necessary; so your generated projects include logic to invoke cmake itself! As all command-line parameters initially passed (e.g. cmake -DCMAKE_BUILD_TYPE=RELEASE .. will be stored in the CMakeCache.txt, you dont need to re-specify any of those on subsequent invocations, which is why the projects also can just run cmake and know it still does what you intended.
Some more detail:
CMake generates book-keeping files containing all files that were involved in Makefile/Project generation, see e.g. these sample contents of my <binary-dir>/CMakeFiles/Makefile.cmake file using MSYS makefiles:
# The top level Makefile was generated from the following files:
set(CMAKE_MAKEFILE_DEPENDS
"CMakeCache.txt"
"C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/CMakeCCompiler.cmake.in"
"C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/RepositoryInfo.txt.in"
"<my external project bin dir>/release/ep_tmp/IRON-cfgcmd.txt.in"
"../CMakeFindModuleWrappers/FindBLAS.cmake"
"../CMakeFindModuleWrappers/FindLAPACK.cmake"
"../CMakeLists.txt"
"../CMakeScripts/CreateLocalConfig.cmake"
"../Config/Variables.cmake"
"../Dependencies.cmake"
"CMakeFiles/3.1.0/CMakeCCompiler.cmake"
"CMakeFiles/3.1.0/CMakeRCCompiler.cmake")
Any modification to any of these files will trigger another cmake run whenever you choose to start a build of a target. I honestly dont know how fine-grained those dependencies tracking goes in CMake, i.e. if a target will just be build if any changes somewhere else wont affect the target's compilation. I wouldn't expect it as this can get messy quite quickly, and repeated CMake runs (correctly using the Cache capabilities) are very fast anyways.
The only case where you need to re-run cmake is when you change the compiler after you started a project(MyProject); but even this case is handled by newer CMake versions automatically now (with some yelling :-)).
additional comment responding to comments:
There are cases where you will need to manually re-run cmake, and that is whenever you write your configure scripts so badly that cmake cannot possibly detect files/dependencies you're creating. A typical scenario would be that your first cmake run creates files using e.g. execute_process and you would then include them using file(GLOB ..). This is BAD style and the CMake Docs for file explicitly say
Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
Btw this comment also sheds light on the above explained self-invocation by the generated build system :-)
The "proper" way to treat this kind of situations where you create source files during configure time is to use add_custom_command(OUTPUT ...), so that CMake is "aware" of a file being generated and tracks changes correctly. If for some reason you can't/won't use add_custom_command, you can still let CMake know of your file generation using the source file property GENERATED. Any source file with this flag set can be hard-coded into target source files and CMake wont complain about missing files at configure time (and expects this file to be generated some time during the (first!) cmake run.
Looking into this topic for reading the version information from a debian/changelog file (generation phase), I ran in the topic that cmake execution should be triggered as debian/changelog is modified. So I had the need to add debian/changelog to CMAKE_MAKEFILE_DEPENDS.
In my case, debian/changelog is read through execute_process. Execute_process unfortunately gives no possibility to add files processed to CMAKE_MAKEFILE_DEPENDS. But I found that running configure_file will do it. Actually I am really missing something like DEPENDENCIES in execute_process.
However, as I had the need to configure the debian/changelog file for my needs, the solution came implicitly to me.
I actually also found a hint about this in the official documentation of configure_file:
"If the input file is modified the build system will re-run CMake to re-configure the file and generate the build system again."
So using configure_file should be a safe to trigger the re-run of cmake.
From a user perspective, I would expect other commands to extend CMAKE_MAKEFILE_DEPENDS, too. E.g. execute_process (on demand) but also file(READ) (implicitly like configure_file). Perhaps there are others. Each read file is likely to influence the generation phase. As an alternative it would be nice to have a command to just extend the dependency list (hint for the cmake developers, perhaps one comes along).
I'm building a very light-weight library/wrapper for OpenGL and I've run into a little problem. Let's say I have a directory structure that looks sort of like this:
GraphicsProject
|GraphicsApp
||main.cpp
|GraphicsLib
||include
|||fileA.h
|||fileB.h
||library
|||fileA.cpp
|||fileB.cpp
||shaders
|||shader1.txt
|||shader2.txt
|| build
||| bunch of build stuff
What is the best way to get the path to shader1.txt at runtime? Or else, make it such that the path will not change no matter who is using this project or where it is located on a user's machine?
Some options I've considered:
1) Get the current working directory and use that path to work my way up to where I need to be. My main concern with this solution is that I'm not sure how much the current directory will change based on how the user builds the project or other factors out of my control. It also doesn't feel very elegant.
2) Store the source code for the shaders as char arrays/strings in a .h file that is in the include directory. This seems like a better solution, except that it would make writing the shaders slightly more cumbersome.
Is there a standard way of doing this? I'm using CMake to build the project, if that changes anything.
I'm assuming you're talking about making the "shaders" folder available to other devs who are building your project, since if you meant end-users (which would involve installing the components) you wouldn't be talking about build folders.
I think the simplest way to provide a fixed location to the shaders folder at runtime is to copy it from your source tree to your build tree. In this way, other devs can place their root build folder anywhere outside your project (or even inside if they want) and the app will still have a single fixed relative path to deal with when accessing the copied shaders folder.
There are other options in case you don't want to copy (e.g. you could have CMake write a config file to the build tree; the config file could specify the path to the shaders folder) but I think they're more complex and probably more fragile. Regardless, I think the crux is to copy info from the source tree to the build tree at configure-time (when CMake executes), so that the runtime code doesn't involve a difficult search for the potentially very distant source tree.
An example root CMakeLists.txt would be:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(example)
add_executable(GraphicsApp GraphicsApp/main.cpp)
add_library(GraphicsLib
GraphicsLib/library/fileA.cpp
GraphicsLib/library/fileB.cpp
GraphicsLib/include/fileA.h
GraphicsLib/include/fileB.h
GraphicsLib/shaders/shader1.txt
GraphicsLib/shaders/shader2.txt
)
include_directories(GraphicsLib/include)
target_link_libraries(GraphicsApp GraphicsLib)
add_custom_command(TARGET GraphicsApp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/GraphicsLib/shaders
$<TARGET_FILE_DIR:GraphicsApp>/shaders)
To expand a little on the add_custom_command call, this basically causes the "shaders" subdirectory to be copied to the folder where GraphicsApp will be built to. The command executes any time GraphicsApp is built. If GraphicsApp is built and up to date and you try and rebuild it, the custom command won't execute.
The custom command actually executes
cmake -E copy_directory <path to shaders source> <path to shaders copy>
making use of CMake's -E cross-platform command mode.
The "destination" part of the command (the "copy to" location) uses a generator expression to deduce the location where GraphicsApp will be built to: $<TARGET_FILE_DIR:GraphicsApp>. This is probably the most robust way of achieving that aim; it will be correct regardless of config type (where e.g. MSVC inserts a "Debug/" or "Release/" folder to the build path).
So this hopefully gets you most of the way to your aim. I imagine you still have to get the full path to the running exe to then deduce the full path to the copied shaders folder. However, this should be much more simple and robust than searching from the current working directory. Even calculating the current working dir is non-trivial.
I'm using CMake for my build system and in the project, we will have a bunch of configuration files. Some of them will just need to be copied over, some will need to be modified per computer. I'm currently using CMake's "configure_file" command to copy/replace parts of the file. This works great, and I love how I can use any variable from CMake in the configure routine.
But if you change the original file, CMake will not pick this up and you have to rerun cmake for it to configure the directory. When I run "make", I want it to pick up that I've changed the file and rerun configure.
It will also reconfigure files always, even if the file it is overwriting is newer. I want it to act like a custom target.
I think I can do this with add_custom_command, but I don't think I can run a CMake command from add_custom_command. So is there anyway to duplicate the behaviour that configure_file does in CMake?
I recently upgraded to CMake 2.8. It seems like it automatically has the exact behavior I wanted.
I do not think this has an easy answer. I see two options:
To trigger a re-run of cmake if an input changes, you might be able to make your input file depend on CMakeLists.txt.
To run a cmake command as part of and add_custom_command, there is the variable ${CMAKE_COMMAND}, which will give you the path to the running cmake. You could, as part of the configure step, generate a fragment of CMake code (that calls configure_file) that is invoked using the -P option. Either pass substitutions on the command line using -D, or write them to the CMake fragment.