在macOS中使用CMake构建多语言项目的方法咨询
Your approach is conceptually sound, but there are a few bugs and opportunities for improvement that will make this more reliable and maintainable.
Key Issues in the Current Code
Let's break down the problems first:
- Typo in Objective-C file handling: In the
.mcase, you're using${SRC_FILE}(uppercase) instead of the loop variable${src_file}(lowercase). This variable is undefined, so those files won't get the correctOBJC_FLAGSapplied. - Incorrect regex patterns: The
MATCHESchecks use patterns like.cpp$, but in regular expressions, the dot (.) matches any character. This means a file namedmycpp.txtwould incorrectly match.cpp$. You need to escape the dot to match it literally, using double backslashes (since CMake escapes backslashes in strings). The correct pattern for.cppis"\\.cpp$". - Potential scope/quoting issues: While not a critical bug here, wrapping the regex pattern in quotes prevents unexpected behavior if your patterns ever include spaces or special characters.
Better Approach: Use CMake's Built-in Language Flags
Instead of manually checking file extensions and setting per-file properties, CMake has native support for language-specific compilation flags. This is the recommended method because it's less error-prone, automatically applies to all files of the corresponding language, and integrates better with CMake's default behavior.
Here's how to rewrite your flags using CMake's standard variables:
# Append your custom flags to CMake's default flags (don't overwrite them!) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch x86_64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch x86_64 -fmessage-length=0 -std=c++11") set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} -fobjc-arc") set(CMAKE_OBJCXX_FLAGS "${CMAKE_OBJCXX_FLAGS} -std=gnu++11 -stdlib=libc++")
Why This Is Better:
- No manual extension checks: CMake automatically detects the language for each file based on its extension (
.c→ C,.cpp→ C++,.m→ Objective-C,.mm→ Objective-C++). - Preserves default flags: By appending your flags to
${CMAKE_C_FLAGS}instead of overwriting, you keep CMake's default compiler flags (like optimization flags for different build types). - Maintainable: Adding new files later doesn't require updating any helper functions—they'll get the correct flags automatically.
Corrected Version of Your Original Function (If You Still Need Per-File Control)
If you have specific cases where you need per-file flags (e.g., overriding global flags for a single file), here's the fixed version of your function:
set(CPP_FLAGS "-x c++ -arch x86_64 -fmessage-length=0 -std=c++11") set(OBJCPP_FLAGS "-x objective-c++ -std=gnu++11 -stdlib=libc++ ") set(OBJC_FLAGS "-x objective-c -fobjc-arc") set(C_FLAGS "-x c -arch x86_64") function(set_src_files_according_to_language in_source_files) foreach(src_file ${in_source_files}) if(${src_file} MATCHES "\\.cpp$") set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${CPP_FLAGS}") elseif(${src_file} MATCHES "\\.mm$") set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${OBJCPP_FLAGS}") elseif(${src_file} MATCHES "\\.m$") set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${OBJC_FLAGS}") elseif(${src_file} MATCHES "\\.c$") set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${C_FLAGS}") endif() endforeach() endfunction()
- Fixed the typo in the
.mcase. - Updated regex patterns to escape dots correctly.
- Removed the redundant
SRCargument fromendforeach(it's optional and inconsistent with the loop variable name).
Content of the question originates from Stack Exchange, asked by Zohar81

