berak
berak

Reputation: 39796

How do I exclude a single file from a cmake `file(GLOB ... )` pattern?

My CMakeLists.txt contains this line:

file(GLOB lib_srcs Half/half.cpp Iex/*.cpp IlmThread/*.cpp Imath/*.cpp IlmImf/*.cpp)

and the IlmImf folder contains b44ExpLogTable.cpp, which I need to exclude from the build.

How to achieve that?

Upvotes: 132

Views: 92101

Answers (5)

Foad S. Farimani
Foad S. Farimani

Reputation: 14016

The accepted answer on this page does not work properly as mentioned here. You must fetch the absolute path to the files you want to exclude. So I developed a simple CMake function based on this proposal:

function(efile out_var)
  set(options)
  set(oneValueArgs GLOB)
  set(multiValueArgs EXCLUDE)
  cmake_parse_arguments(EFILE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

  # Use file(GLOB ...) to collect all files matching the provided patterns
  file(GLOB_RECURSE temp_files CONFIGURE_DEPENDS ${EFILE_GLOB})

  # Apply exclusions
  foreach(exclude_pattern ${EFILE_EXCLUDE})
    # Filtering out files from the list that match the exclude patterns
    list(FILTER temp_files EXCLUDE REGEX "${exclude_pattern}")
  endforeach()

  # Set the results to the output variable
  set(${out_var} "${temp_files}" PARENT_SCOPE)
endfunction()

And you may use the efile function, standing for extended file, in your CMake project:

# Assuming you want to include all C files in the src directory but exclude the main.c file
efile(my_sources GLOB "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" EXCLUDE "main.c")

# Print the list of files collected
message("Sources: ${my_sources}")

please give it a try and let me know if it works properly.

Upvotes: 0

Marek R
Marek R

Reputation: 37697

I have an alternative solution worth noticing: mark source as header file. This way it will not be part of the build process, but will be visible in IDE (verified on Visual Studio and Xcode):

set_source_files_properties(b44ExpLogTable.cpp,
                            PROPERTIES HEADER_FILE_ONLY TRUE)

I use this when some source file is platform specific. It is great since if some symbol has to be modified in many places and working on one platform then other platform specific source will can be visible and can be updated too.

For that I've created a helper function which works great in my current project.

I didn't use this method with file GLOB yet.

Upvotes: 0

Eugene
Eugene

Reputation: 3417

FILTER is another option which could be more convenient in some cases:

list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)

This line excludes every item ending with the required filename:

list(FILTER lib_srcs EXCLUDE REGEX ".*b44ExpLogTable\\.cpp$")

Here is Regex Specification for cmake:

The following characters have special meaning in regular expressions:

^         Matches at the beginning of input
$         Matches at the end of input
.         Matches any single character
[ ]       Matches any character(s) inside the brackets
[^ ]      Matches any character(s) not inside the brackets
 -        Inside brackets, specifies an inclusive range between
          characters on either side e.g. [a-f] is [abcdef]
          To match a literal - using brackets, make it the first
          or the last character e.g. [+*/-] matches basic
          mathematical operators.
*         Matches preceding pattern zero or more times
+         Matches preceding pattern one or more times
?         Matches preceding pattern zero or once only
|         Matches a pattern on either side of the |
()        Saves a matched subexpression, which can be referenced
          in the REGEX REPLACE operation. Additionally it is saved
          by all regular expression-related commands, including
          e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).

Upvotes: 86

James
James

Reputation: 129

try this : CMakeLists.txt

install(DIRECTORY   ${CMAKE_SOURCE_DIR}/ 
            DESTINATION ${CMAKE_INSTALL_PREFIX}
            COMPONENT   copy-files
            PATTERN     ".git*"   EXCLUDE
            PATTERN     "*.in"    EXCLUDE
            PATTERN     "*/build" EXCLUDE)

add_custom_target(copy-files
            COMMAND ${CMAKE_COMMAND} -D COMPONENT=copy-files
            -P cmake_install.cmake)
$cmake <src_path> -DCMAKE_INSTALL_PREFIX=<install_path>
$cmake --build . --target copy-files

Upvotes: 4

Lindydancer
Lindydancer

Reputation: 26094

You can use the list function to manipulate the list, for example:

list(REMOVE_ITEM <list> <value> [<value> ...])

In your case, maybe something like this will work:

list(REMOVE_ITEM lib_srcs "IlmImf/b44ExpLogTable.cpp")

Upvotes: 138

Related Questions