title: Dealing with os/platform specific code in cmake
body: <p>In the multi-platform/os project I'm working on, I'm striving to simplify the platform specific code into subdirectories, with a common directory holding a common implementation.  I have a prototype implementation in autotools, but want to move to a cmake implementation if possible.  My current sticking point is how to support multiple OSes.  My current filesystem structure looks like the following:</p>
  
  <pre><code>/* A common header file for all platforms that presents an interface */
  include/my_socket_utils.h
  include/my_time_utils.h
  
  /* Platform specific source files */
  src/common/my_socket_utils.cpp
  src/linux/my_socket_utils.cpp 
  src/vxworks/my_socket_utils.cpp 
  src/qnx/my_socket_utils.cpp 
  
  src/common/my_time_utils.cpp
  src/vxworks/my_time_utils.cpp
  </code></pre>
  
  <p>The idea is that there is a common interface and a "common" implementation.  The implementation is either a stub or a common implementation written to a posix standard that allows it to work for most platforms.  Those platforms that require a custom implementation MAY override the common one, but it's optional.</p>
  
  <p>With autotools, I am able to achieve this using VPATH to set a source tree hierarchy, so I set:</p>
  
  <pre><code>VPATH=@srcdir@/src/@target_platform@;@srcdir@/src/common
  </code></pre>
  
  <p>This makes autotools look for the source file in src/@target_platform@ first, then, if it wasn't found, grab it from src/common.</p>
  
  <p>What is the cmake way to do this?</p>
  
  <p>Update:
  To help all those lost souls in need, this is what I ended up doing for the time being. I'm not sure it's the best solution, but it works well enough.</p>
  
  <p>FILE(GLOB common_files "src/common/<em>.c</em>")
  FILE(GLOB platform_files "src/${os}/<em>.c</em>)</p>
  
  <p>Then, do the dirty n^2 algorithm to override.  Not sure how to do any better in cmake "script", but the number of files is low, so it's plenty fast.  The diag messages are, of course, optional.</p>
  
  <pre><code>#
  # For each common file, check to see if a platform file exists to override it.
  #
  foreach(fqfn ${common_files})
      set(platform_override FALSE)
      get_filename_component(filename ${fqfn} NAME)
      # 
      # If filename exists in platform, override it with the platform,
      # otherwise fall back to the common implementation.  Oh for a real
      # language.
      #
  
      foreach(platform_fqfn ${platform_files})
          get_filename_component(platform_filename ${platform_fqfn} NAME)
          message("pf=${platform_filename} cf=${filename}")
          if(filename STREQUAL platform_filename)
              message("filename == platform_filename")
              list(APPEND proj_files ${platform_fqfn})
              set(platform_override TRUE)
          endif(filename STREQUAL platform_filename)
      endforeach(platform_fqfn ${platform_files})
  
      if(NOT ${platform_override})
          list(APPEND proj_files ${fqfn})
          message("Appended ${fqfn}")
      endif(NOT ${platform_override})
  endforeach(fqfn ${common_files})
  
  message("proj_files=${proj_files}")
  add_executable (cc_dfi_main ${proj_files})
  </code></pre>