Ah, I found the problem. I had the output file listed in the custom command's DEPEND clause.
Thank you very much for all the help! On Fri, Jan 30, 2015 at 11:07 AM, Chris Johnson <cxjohn...@gmail.com> wrote: > I'm trying to use the method outlined in your #2, with the list of files. > But I get circular dependency errors, with messages like this one (for each > file): > > make[2]: Circular validate/X12_Standards/997_5010.x12 <- > validate/X12_Standards/997_5010.x12 dependency dropped. > > On Fri, Jan 30, 2015 at 10:28 AM, Petr Kmoch <petr.km...@gmail.com> wrote: > >> I believe the classic "driving target" approach could be used here. Add a >> custom target which will drive the custom commands by depending on their >> outputs: >> >> add_custom_target( >> RunMyProg ALL >> DEPENDS >> ${CMAKE_CURRENT_BINARY_DIR}/file001.out >> ${CMAKE_CURRENT_BINARY_DIR}/file002.out >> #... >> COMMENT "Processing files with MyProg" >> ) >> >> Notice the ALL after the target name - this makes the target part of >> 'make all' or equivalent. >> >> Custom targets are always considered out of date (always rebuilt), but >> this one has no COMMAND and so building it does nothing. It does make sure >> all its dependencies (the .out files) are up to date, though, and if they >> are not, it will run the rules to build them. These rules are the custom >> commands you've created earlier. >> >> This "custom target driving custom commands" is a very idiomatic pattern >> in CMake. >> >> Of course, you don't want to list the files by hand. You could modify my >> earlier function in one of two ways: >> >> 1. Have each invocation append to a list: >> >> set(OutputFileList "") >> >> function(ProcessFile inFile) >> get_filename_component(outFile ${inFile} NAME_WE) >> set(outFile ${inFile}.out) >> add_custom_command( >> OUTPUT ${outFile} >> COMMAND ${CMAKE_COMMAND} -E copy >> ${CMAKE_CURRENT_SOURCE_DIR}/${inFile} ${CMAKE_CURRENT_BINARY_DIR} >> COMMAND myprog ${inFile} ${outFile} >> DEPENDS ${inFile} myprog.cpp >> ) >> install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${outFile} DESTINATION >> share/docs) >> set(OutputFileList ${OutputFileList} >> ${CMAKE_CURRENT_BINARY_DIR}/${outFile} PARENT_SCOPE) # This line is new >> endfunction() >> >> # process files >> ProcessFile(file001.in) >> ProcessFile(file002.in) >> ProcessFile(file003.in) >> >> >> # now use the list in the custom target: >> add_custom_target( >> RunMyProg ALL >> DEPENDS ${OutputFileList} >> COMMENT "Processing files with MyProg" >> ) >> >> >> Or, 2., refactor the function to take a list of files and do everything >> itself: >> >> function(ProcessFiles) >> set(OutputFileList "") >> foreach(inFile IN LISTS ARGN) >> get_filename_component(outFile ${inFile} NAME_WE) >> set(outFile ${inFile}.out) >> add_custom_command( >> OUTPUT ${outFile} >> COMMAND ${CMAKE_COMMAND} -E copy >> ${CMAKE_CURRENT_SOURCE_DIR}/${inFile} ${CMAKE_CURRENT_BINARY_DIR} >> COMMAND myprog ${inFile} ${outFile} >> DEPENDS ${inFile} myprog.cpp >> ) >> list(APPEND OutputFileList ${CMAKE_CURRENT_BINARY_DIR}/${outFile}) >> endforeach() >> install(FILES ${OutputFileList} DESTINATION share/docs) >> add_custom_target( >> RunMyProg ALL >> DEPENDS ${OutputFileList} >> COMMENT "Processing files with MyProg" >> ) >> endfunction() >> >> # now just call it once with the list of files: >> ProcessFiles( >> file001.in >> file002.in >> file003.in >> ) >> >> >> You can naturally enlist file(GLOB) to grab the list of files, as J >> Decker suggests. The downside, as with any list of source files, is that >> CMake will not know that it needs to re-run when you simply add a new file >> which matches the glob. If you list the files explicitly, you have to edit >> the CMakeList to add the file, and CMake will know to re-run at next build. >> >> Petr >> >> >> >> >> >> On Fri, Jan 30, 2015 at 4:40 PM, Chris Johnson <cxjohn...@gmail.com> >> wrote: >> >>> Petr, thanks. That makes a lot of sense. >>> >>> Now I am struggling with causing all of these files to be generated when >>> I do the default build target, e.g. just "make" in the build directory. >>> That is, I want myprog to be compiled, and then all of the files processed >>> by it with just one build command. I assume that's possible, but have not >>> quite yet been able to make it happen. >>> >>> On Fri, Jan 30, 2015 at 9:11 AM, Petr Kmoch <petr.km...@gmail.com> >>> wrote: >>> >>>> As you say, **make** is fairly powerful at this. Other build tools may >>>> not be, it might even be an alien concept to them. AFAIK, Ninja requires an >>>> explicit list of files & dependencies, for example. Visual Studio solutions >>>> can only contain explicitly listed files too. >>>> >>>> CMake projects are supposed to work with all generators which CMake >>>> supports (within reason). There are some generator-specific features in >>>> CMake, but the intent is to keep the set of these to a minimum. >>>> >>>> The list of CMake commands which directly create build-time "commands" >>>> (such as Makefile rules) is rather short: >>>> >>>> add_custom_command() >>>> add_custom_target() >>>> add_executable() >>>> add_library() >>>> >>>> Other commands modify the buildsystem (e.g. add_definitions(), >>>> target_link_libraries(), or setting properties such as COMPILE_OPTIONS), >>>> but they don't really add "commands" to it. >>>> >>>> Petr >>>> >>>> >>>> On Fri, Jan 30, 2015 at 3:27 PM, Chris Johnson <cxjohn...@gmail.com> >>>> wrote: >>>> >>>>> That does clarify a few things yes. Thank you. >>>>> >>>>> By "configure" time I had meant the first two items you listed as >>>>> Configure and Generate. By "run" time I had meant what you called Build. >>>>> >>>>> One place I am unclear on is exactly which commands in CMakeLists.txt >>>>> get translated into Build time commands in buildsystem files (in my case, >>>>> make). For example, make is fairly powerful at generating substitution >>>>> file names, e.g. creating prog.o from prog.cpp, or file1.out from >>>>> file1.in. Make is also capable of running full shell scripts within >>>>> a makefile. But there's no obvious way to drive any kind of automation >>>>> from CMake that make is capable of. >>>>> >>>>> As a programmer, my first thought when having to process a large list >>>>> of files is to do it through some sort of automation, rather than generate >>>>> a brute force solution. It appears that with CMake, the best one can hope >>>>> for is to automate the creation of the brute-force solution. >>>>> >>>>> -- >>>>> Cheers, >>>>> ..chris >>>>> >>>>> On Fri, Jan 30, 2015 at 4:32 AM, Petr Kmoch <petr.km...@gmail.com> >>>>> wrote: >>>>> >>>>>> It's not clear to me what you mean with "run" time. There are the >>>>>> following "times" involved in a CMake-based project: >>>>>> >>>>>> * Configure time: >>>>>> CMake is parsing CMakeLists.txt files and files included from those >>>>>> and executing ALL CMake commands found in them. Variables expansion takes >>>>>> place. Data structures in CMake's memory are filled. >>>>>> >>>>>> * Generate time: >>>>>> CMake processes the data structures in its memory to write >>>>>> buildsystem files (Makefiles, solutions etc.) to disk. Generator >>>>>> expressions are expanded. Files are generated from data specified in >>>>>> file(GENERATE ...) commands. cmake_install.cmake file is written based on >>>>>> the contents of data structures filled by install() commands. >>>>>> >>>>>> * Build time: >>>>>> CMake is not running (except for driving the build if you do that >>>>>> with `cmake --build`). The build tool (make, ninja, devenv, msbuild, ...) >>>>>> is running, processing the buildsystem files and generating compiled >>>>>> binaries. At this time, commands which were set up by >>>>>> add_custom_command() >>>>>> and add_custom_target() are executed as driven by the build tool. >>>>>> >>>>>> * Install time (optional): >>>>>> Running `make install` or similarly triggering the install process >>>>>> causes CMake to run in installation mode. This CMake reads the >>>>>> cmake_install.cmake file and executes the commands there. These are >>>>>> mainly >>>>>> file() commands which copy files to the desired location. >>>>>> >>>>>> CMake commands in CMakeLists.txt and included files are all executed >>>>>> during configure time, as the files are parsed and processed by CMake. >>>>>> Some >>>>>> of these commands have immediate effects on the outside environment (e.g. >>>>>> file(WRITE), execute_process(), try_compile()), some affect the CMake >>>>>> processing control flow (e.g. include(), foreach()), some fill in or >>>>>> modify >>>>>> CMake's data structures (e.g. set(), add_executable(), install(), >>>>>> add_custom_command()). >>>>>> >>>>>> So there are no CMake commands executed after configure time. The >>>>>> value specified in a COMMAND argument of add_custom_command() executes at >>>>>> build time (driven by the build system), but the add_custom_command() >>>>>> itself executes at CMake time. >>>>>> >>>>>> I hope I've clarified it a little bit. >>>>>> >>>>>> Petr >>>>>> >>>>>> >>>>>> >>>>>> On Thu, Jan 29, 2015 at 9:36 PM, Chris Johnson <cxjohn...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> Thanks; I appreciate the suggestions. >>>>>>> >>>>>>> One thing that jumped out is the thought that foreach() is executed >>>>>>> at "configuration" time, not "run" time. To me, that was >>>>>>> counter-intuitive, but makes more sense once more thoroughly considered. >>>>>>> >>>>>>> But I have to admit, I've never seen anything in the documentation >>>>>>> which lists all of the commands which execute at configuration time, and >>>>>>> which are executed at run time. Is there such documentation? A link >>>>>>> to it >>>>>>> would be great. >>>>>>> >>>>>>> On Thu, Jan 29, 2015 at 9:51 AM, Thompson, KT <k...@lanl.gov> wrote: >>>>>>> >>>>>>>> Hi Chris, >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Why not use a foreach loop? Something like this… >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> add_executable(myprog myprog.cpp) >>>>>>>> >>>>>>>> set( files file001 fiile002 …) >>>>>>>> >>>>>>>> foreach( file in files) >>>>>>>> >>>>>>>> add_custom_command(OUTPUT ${file}.out >>>>>>>> >>>>>>>> COMMAND /bin/cp ${CMAKE_CURRENT_SOURCE_DIR}/${file}.in . >>>>>>>> >>>>>>>> COMMAND myprog ${file}.in ${file}.out >>>>>>>> >>>>>>>> DEPENDS ${file}.in myprog.cpp >>>>>>>> >>>>>>>> ) >>>>>>>> >>>>>>>> endforeach() >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> For portability, you might want to use ‘${CMAKE_COMMAND} –E >>>>>>>> copy_if_different’ in place of ‘/bin/cp’ and CMAKE_CURRENT_BINARY_DIR >>>>>>>> in >>>>>>>> place of ‘.’ >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -kt >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> *From:* CMake [mailto:cmake-boun...@cmake.org] *On Behalf Of *Chris >>>>>>>> Johnson >>>>>>>> *Sent:* Thursday, January 29, 2015 8:09 AM >>>>>>>> *To:* cmake@cmake.org >>>>>>>> *Subject:* [CMake] Generated files? >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> I am looking for suggestions on how to solve the following >>>>>>>> problem. I need a solution which is easy to understand and safe from >>>>>>>> future maintenance errors. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> There is a project directory with one C++ program and a large >>>>>>>> number of "input" data files. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> The C++ program needs to be compiled, and then run against each of >>>>>>>> the input files to generate an output file of the same base name but >>>>>>>> with a >>>>>>>> different output suffix. E.g. from the command line it might be: >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> % myprog file001.in file001.out >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Finally, the output files need to be installed in the proper >>>>>>>> location. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> For one input file, it might look like this: >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> add_executable(myprog myprog.cpp) >>>>>>>> >>>>>>>> add_custom_command(OUTPUT file001.out >>>>>>>> >>>>>>>> COMMAND /bin/cp ${CMAKE_CURRENT_SOURCE_DIR}/file001.in . >>>>>>>> >>>>>>>> COMMAND myprog file001.in file001.out >>>>>>>> >>>>>>>> DEPENDS files001.in myprog.cpp >>>>>>>> >>>>>>>> ) >>>>>>>> >>>>>>>> install(FILES ${CMAKE_CURRENT_BINARY_DIR}/file001.out >>>>>>>> DESTINATION share/docs) >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Listing all of the input files in my CMakeLists.txt file is not a >>>>>>>> problem, but it would be nice to avoid having to list the corresponding >>>>>>>> output files. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> How can I build a CMakeLists.txt file which will succinctly handle >>>>>>>> this situation? >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> ..chris >>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> >>>>>>> Powered by www.kitware.com >>>>>>> >>>>>>> Please keep messages on-topic and check the CMake FAQ at: >>>>>>> http://www.cmake.org/Wiki/CMake_FAQ >>>>>>> >>>>>>> Kitware offers various services to support the CMake community. For >>>>>>> more information on each offering, please visit: >>>>>>> >>>>>>> CMake Support: http://cmake.org/cmake/help/support.html >>>>>>> CMake Consulting: http://cmake.org/cmake/help/consulting.html >>>>>>> CMake Training Courses: http://cmake.org/cmake/help/training.html >>>>>>> >>>>>>> Visit other Kitware open-source projects at >>>>>>> http://www.kitware.com/opensource/opensource.html >>>>>>> >>>>>>> Follow this link to subscribe/unsubscribe: >>>>>>> http://public.kitware.com/mailman/listinfo/cmake >>>>>>> >>>>>> >>>>>> >>>>> >>>> >>> >> >
-- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake