CMake WRAP_EXCLUDE Property for Selective Code Wrapping


Purpose

The WRAP_EXCLUDE property in CMake is used to specifically prevent a source file from being included in any code wrapping techniques employed during the build process.

Code Wrapping

Code wrapping refers to the process of translating source code written in one language (like C++) into a different language (like Python or Java) to enable easier integration with other systems or languages. Tools like SWIG (Simplified Wrapper and Interface Generator) are commonly used for this purpose.

How WRAP_EXCLUDE Works

By setting the WRAP_EXCLUDE property to TRUE on a source file, you instruct CMake to explicitly exclude that file from being considered for code wrapping. This is useful in scenarios where:

  • You already have a separate mechanism for exposing the functionality of the file (e.g., manual creation of bindings).
  • The file interacts with system-specific functionalities that wouldn't translate well to another language.
  • The source file contains implementation details that aren't meant to be exposed through the wrapped interface.

Setting WRAP_EXCLUDE

You can set the WRAP_EXCLUDE property on a source file using the set_source_files_properties command within your CMakeLists.txt file:

set_source_files_properties(
    my_source_file.cpp  # Replace with the actual file path
    PROPERTIES WRAP_EXCLUDE TRUE
)

Example

Imagine you have a C++ project with a source file named internal_functions.cpp containing helper functions that aren't intended for external use. You wouldn't want these functions to be wrapped, so you can set the WRAP_EXCLUDE property on this file:

set_source_files_properties(
    internal_functions.cpp
    PROPERTIES WRAP_EXCLUDE TRUE
)


Scenario 1: Excluding a File with Internal Functions

# CMakeLists.txt

# Source files
set(SOURCE_FILES main.cpp helper_functions.cpp)

# Excluding helper_functions.cpp from code wrapping
set_source_files_properties(
    helper_functions.cpp
    PROPERTIES WRAP_EXCLUDE TRUE
)

# Target creation (assuming you're building an executable)
add_executable(my_program ${SOURCE_FILES})

In this example:

  • We create an executable named my_program using both source files.
  • We set the WRAP_EXCLUDE property to TRUE on helper_functions.cpp, ensuring it's not wrapped.
  • We have two source files: main.cpp (likely containing the main logic) and helper_functions.cpp (containing internal helper functions).
# CMakeLists.txt

# Source files
set(SOURCE_FILES main.cpp my_library.cpp)

# Header for wrapping (assuming it exposes the desired functionality)
set(WRAP_HEADER my_library.h)

# Excluding my_library.cpp (implementation details)
set_source_files_properties(
    my_library.cpp
    PROPERTIES WRAP_EXCLUDE TRUE
)

# Target creation (assuming you're building a library)
add_library(my_library SHARED ${SOURCE_FILES} ${WRAP_HEADER})
  • We create a shared library named my_library using all three files.
  • We exclude my_library.cpp from wrapping.
  • We define a separate header my_library.h that exposes the public interface for wrapping.
  • We have main.cpp (likely using the library) and my_library.cpp (containing the library implementation).


    • Instead of excluding files, you can create separate targets for wrapping and non-wrapping parts. This can be useful for complex projects with various wrapping needs.
    # CMakeLists.txt
    
    set(SOURCE_FILES main.cpp helper_functions.cpp)
    
    # Target for non-wrapped code (assuming executable)
    add_executable(my_program ${SOURCE_FILES})
    
    # Target for wrapped code (assuming you have SWIG setup)
    # This would likely involve additional steps for SWIG configuration
    add_custom_command(
        OUTPUT wrapped_library.py
        COMMAND swig -python helper_functions.cpp -o wrapped_library.py
        DEPENDS helper_functions.cpp
    )
    
    # You can then link the wrapped library with your main program if needed
    
  1. Manual Source File Inclusion

    • If you're using a custom code wrapping tool, you might have more control over the specific files included. You can directly specify the source files to the wrapping tool, bypassing CMake's automatic inclusion.
  2. Header-Only Libraries

    • For certain scenarios, consider creating a header-only library. This eliminates the need for separate implementation files and simplifies the wrapping process since only the header is involved.

The best approach depends on your specific project structure, wrapping tool, and desired level of granularity.

Choosing the Right Method

  • Header-only libraries are ideal when the functionality can be entirely encapsulated in headers.
  • If you have a custom wrapping tool, manual source file inclusion might be suitable.
  • For more complex projects with multiple wrapping needs, target-specific source files offer more flexibility.
  • If you have a clear separation between public and private code, WRAP_EXCLUDE is a straightforward solution.