Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake Option to Disable Compilation on Specific Files for Specific Platforms

I am using CMake to define my projects. My goal is to have platform-specific files easily accessible for editing, searching, browsing, and source control with across all platforms.

I currently have platform-specific files separated in the cmake description. My CMakeLists.txt file looks something like the following:

 Foo.hpp
 ${platform_directory}/Foo.cpp

Then on disk I have something like this:

 Foo.hpp
 win
  `- Foo.cpp 
 osx
  `- Foo.cpp 

Which in the generated project file looks like:

 Foo.hpp
 Foo.cpp (platform-specific version)

This is perfect for the compiler, but it means that developers lack IDE tooling for non-native platform-specific files.

What I am looking for is something like this (in Xcode):

 Foo.hpp
 Foo.cpp (OS X version)
 win
  `- Foo.cpp (file type set to plain text)

Or in Visual Studio:

 Foo.hpp
 Foo.cpp (Windows version)
 osx
  `- Foo.cpp (build action set to none)

Any ideas on how something like this can be setup CMake?

like image 724
Kevin Avatar asked Feb 17 '23 17:02

Kevin


2 Answers

One way would be to add a custom target with no build rules, specifically to hold the files which aren't part of the given platform's build; e.g.

if(WIN32)
  add_library(Foo Foo.hpp win/Foo.cpp)
  add_custom_target(NonWindows SOURCES osx/Foo.cpp)
  source_group("osx" osx/Foo.cpp)
else(APPLE)
  add_library(Foo Foo.hpp osx/Foo.cpp)
  add_custom_target(NonApple SOURCES win/Foo.cpp)
  source_group("win" win/Foo.cpp)
endif()

Another option (perhaps closer to what you want, but a bit more "hacky") is to add all the files to the target, but mark the ones not required for the build as HEADER_FILE_ONLY:

add_library(Foo Foo.hpp win/Foo.cpp osx/Foo.cpp)
if(WIN32)
  set_source_files_properties(osx/Foo.cpp PROPERTIES HEADER_FILE_ONLY TRUE)
  source_group("osx" osx/Foo.cpp)
else(APPLE)
  set_source_files_properties(win/Foo.cpp PROPERTIES HEADER_FILE_ONLY TRUE)
  source_group("win" win/Foo.cpp)
endif()
like image 147
Fraser Avatar answered Mar 26 '23 04:03

Fraser


The HEADER_FILE_ONLY technique suggested by Fraser works great, but explicitly configuring which files should be complied on which platform gets tedious.

Given a CMake function as follows:

function (DisableCompilingPlatformSpecificSources file_list)
   foreach(file ${file_list})
      if (
         ((${file} MATCHES "^(.*)Win32\\.cpp") AND NOT WIN32) OR
         ((${file} MATCHES "^(.*)Unix\\.cpp")  AND NOT UNIX)  OR
         ((${file} MATCHES "^(.*)Apple\\.cpp") AND NOT APPLE)
      )
         set_source_files_properties(
            ${file}
            PROPERTIES HEADER_FILE_ONLY TRUE
         )
      endif()
   endforeach()
endfunction()

We can control platform-specific sources by means of their suffix. For example:

set(all_sources
   Foo.hpp
   FooWin32.cpp # windows-specific
   FooApple.cpp # apple-specific
)

DisableCompilingPlatformSpecificSources("${all_sources}")

add_executable(foo ${all_sources})

This is quite similar to how gyp handles platform-specific files and can be easily extended to support additional suffixes as needed.

like image 20
Kevin Avatar answered Mar 26 '23 03:03

Kevin