<br><br><div class="gmail_quote">On Tue, Sep 13, 2011 at 1:58 PM, David Cole <span dir="ltr">&lt;<a href="mailto:david.cole@kitware.com">david.cole@kitware.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><div></div><div class="h5">On Tue, Sep 13, 2011 at 1:39 PM, Alexander Neundorf<br>
&lt;<a href="mailto:a.neundorf-work@gmx.net">a.neundorf-work@gmx.net</a>&gt; wrote:<br>
&gt; On Tuesday, September 13, 2011 05:07:00 AM Clifford Yapp wrote:<br>
&gt;&gt; I am trying to compare two large lists of file paths (about 14,000 lines<br>
&gt;&gt; each) to identify which entries in each list are missing from the other,<br>
&gt;&gt; and while I can get CMake to do it I must be doing it the wrong way<br>
&gt;&gt; because the results are hideously slow.<br>
&gt;&gt;<br>
&gt;&gt; I currently generate two files with the paths and then read them in as<br>
&gt;&gt; lists, using LIST() commands to peform STREQUAL tests.  I was hoping to<br>
&gt;<br>
&gt; How do you do that ?<br>
&gt; Do you iterate over one list using foreach() and then list(FIND) to check<br>
&gt; whether it exists in the other list ?<br></div></div></blockquote><div><br>I tried a couple of ways, most of them variations on that theme (BUILD_FILES and SVN_FILES are two manifest lists, and I need items from each list that are not in the other list)<br>
<br>FOREACH(ITEM ${BUILD_FILES})<br>     LIST(FIND ${ITEM} SVN_FILES POS)<br>     IF(NOT POS STREQUAL &quot;-1&quot;)<br>        LIST(REMOVE_ITEM SVN_FILES ${ITEM})<br>        LIST(REMOVE_ITEM BUILD_FILES ${ITEM})<br>     ENDIF()<br>
ENDFOREACH()<br><br>In essence, the idea is BUILD_FILES will end  up holding items unique to BUILD_FILES and SVN_FILES will end up holding items unique to SVN_FILES, which are the two pieces of information I&#39;m after.<br>
 </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><div class="h5">
&gt; Internally, every cmake variable is stored as a plain std::string.<br>
&gt; When using a list() command, this string is converted to a<br>
&gt; std::vector&lt;std::string&gt;, and then cmake operates on this vector.<br>
&gt; So if you do this 14000 times, each time a 14000 std::strings are created,<br>
&gt; which makes this O(n^2) I think.<br>
&gt;<br>
&gt; Maybe something like this works ?<br>
&gt;<br>
&gt; set(uniqueItems ${list1} ${list2})<br>
&gt; list(REMOVE_DUPLICATES uniqueItems )<br></div></div></blockquote><div><br>I thought about REMOVE_DUPLICATES, but if I understand correctly wouldn&#39;t that give me the union of the two lists?  I need everything not present in both lists.  <br>
</div><div> <br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
I realize this same technique will not be very useful with files<br>
14,000 lines long... but thought I&#39;d mention it so you could look at<br>
it and perhaps draw inspiration from it.<br></blockquote><div><br>Basically I&#39;m currently trying a variation on that, except I&#39;m trying to get a cross-platform comparing tool working that I can guarantee will be there - I&#39;m trying comm at the moment but I&#39;m not sure comm&#39;s notions of what consistute a sorted file and CMake&#39;s LIST(SORT are compatible when it comes to things like .file and ~file.<br>
 </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
If you could pass along the code that you&#39;re using, we might be able<br>
to suggest a better way to achieve the same thing within the CMake<br>
language if that&#39;s absolutely necessary.<br></blockquote></div><br>Currently (using comm) I&#39;m doing this (replacing /. with /tmpdot in an attempt to let comm handle the sorted output):<br><br>STRING(REGEX REPLACE &quot;/\\.&quot; &quot;/tmpdot&quot; BUILD_FILES &quot;${BUILD_FILES}&quot;)<br>
STRING(REGEX REPLACE &quot;/\\.&quot; &quot;/tmpdot&quot; SVN_FILES &quot;${SVN_FILES}&quot;)<br>LIST(SORT BUILD_FILES)<br>LIST(SORT SVN_FILES)<br>STRING(REGEX REPLACE &quot;;&quot; &quot;\n&quot; BUILD_FILES &quot;${BUILD_FILES}&quot;)<br>
STRING(REGEX REPLACE &quot;;&quot; &quot;\n&quot; SVN_FILES &quot;${SVN_FILES}&quot;)<br>FILE(WRITE @CMAKE_BINARY_DIR@/build_files_list.txt ${BUILD_FILES})<br>FILE(WRITE @CMAKE_BINARY_DIR@/svn_files_list.txt ${SVN_FILES})<br>
STRING(REGEX REPLACE &quot;\n&quot; &quot;;&quot; BUILD_FILES &quot;${BUILD_FILES}&quot;)<br>STRING(REGEX REPLACE &quot;\n&quot; &quot;;&quot; SVN_FILES &quot;${SVN_FILES}&quot;)<br><br>EXECUTE_PROCESS(COMMAND @CMAKE_BINARY_DIR@/@BIN_DIR@/comm -3 @CMAKE_BINARY_DIR@/build_files_list.txt @CMAKE_BINARY_DIR@/svn_files_list.txt OUTPUT_VARIABLE COMM_RAWOUT)<br>
STRING(REGEX REPLACE &quot;\n&quot; &quot;;&quot; COMM_OUT &quot;${COMM_RAWOUT}&quot;)<br>STRING(REGEX REPLACE &quot;/tmpdot&quot; &quot;/\\\\.&quot; COMM_OUT &quot;${COMM_OUT}&quot;)<br>STRING(REGEX REPLACE &quot;\\\\&quot; &quot;&quot; COMM_OUT &quot;${COMM_OUT}&quot;)<br>
<br>FOREACH(ITEM ${COMM_OUT})<br>   LIST(FIND BUILD_FILES ${ITEM} INBUILD)<br>   LIST(FIND SVN_FILES ${ITEM} INSVN)<br>   IF(INBUILD STREQUAL &quot;-1&quot; AND NOT INSVN STREQUAL &quot;-1&quot;)<br>      LIST(APPEND SVN_FILES_NOT_IN_BUILD ${ITEM})<br>
      LIST(REMOVE_ITEM COMM_OUT ${ITEM})<br>   ENDIF(INBUILD STREQUAL &quot;-1&quot; AND NOT INSVN STREQUAL &quot;-1&quot;)<br>   IF(INSVN STREQUAL &quot;-1&quot; AND NOT INBUILD STREQUAL &quot;-1&quot;)<br>      LIST(APPEND BUILD_FILES_NOT_IN_SVN ${ITEM})<br>
      LIST(REMOVE_ITEM COMM_OUT ${ITEM})<br>   ENDIF(INSVN STREQUAL &quot;-1&quot; AND NOT INBUILD STREQUAL &quot;-1&quot;)<br>ENDFOREACH(ITEM ${COMM_OUT})<br><br>I was hoping that CMake&#39;s diff ability might indicate lurking in there was the ability to get actual diff style output from a cmake -E command that could be parsed (if CMake had sucked in openbsd&#39;s diff to implement its diff abilities, for example) but if not it looks like performance considerations will require ensuring some sort of cross-platform tool is available.  Would it perhaps make sense to  have a cmake -E diff the same way there is a cmake -E tar?<br>
<br>The broader context is implementing a &quot;make distcheck&quot; rule for BRL-CAD along the lines of the one previously implemented in autotools - the idea is to have subversion tell us what files are in the repository (svn info), have the build system report what files it knows about (via some custom CMake function/macro logic that we have working to record that) and crank that information back into user reporting and cpack (for example, a file known to subversion but not addressed in the build logic is a FATAL_ERROR, and a file unknown to both subversion and the build logic will be ignored when running CPack).  This ability has proven very useful over the years with our autotools build for making tarball distributions (there are more steps to distcheck but this looks to be the last really tricky one to do in CMake).<br>
<br>Cheers, and thanks everybody for the help!<br><br>CY<br>