From ae80cb9f28c8c278a6897f331f65a1be77058897 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 May 2014 13:50:26 -0400 Subject: [PATCH 1/2] Xcode: Refactor internal source file type selection Choose the attribute name and file type and send them through a single attribute generation code path. Compute the file extension only when needed. Leave the file type selection logic indented in a block so it can be made conditional later. --- Source/cmGlobalXCodeGenerator.cxx | 52 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d44da3794..ac75fc233 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -848,35 +848,35 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( } fileRef->AddAttribute("fileEncoding", this->CreateString("4")); - // Compute the extension. - std::string ext; - std::string realExt = - cmSystemTools::GetFilenameLastExtension(fullpath); - if(!realExt.empty()) + bool useLastKnownFileType = false; + std::string fileType; { - // Extension without the leading '.'. - ext = realExt.substr(1); + // If fullpath references a directory, then we need to specify + // lastKnownFileType as folder in order for Xcode to be able to + // open the contents of the folder. + // (Xcode 4.6 does not like explicitFileType=folder). + if(cmSystemTools::FileIsDirectory(fullpath.c_str())) + { + fileType = "folder"; + useLastKnownFileType = true; + } + else + { + // Compute the extension without leading '.'. + std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath); + if(!ext.empty()) + { + ext = ext.substr(1); + } + + fileType = GetSourcecodeValueFromFileExtension( + ext, lang, useLastKnownFileType); + } } - // If fullpath references a directory, then we need to specify - // lastKnownFileType as folder in order for Xcode to be able to open the - // contents of the folder (Xcode 4.6 does not like explicitFileType=folder). - if(cmSystemTools::FileIsDirectory(fullpath.c_str())) - { - fileRef->AddAttribute("lastKnownFileType", - this->CreateString("folder")); - } - else - { - bool keepLastKnownFileType = false; - std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, - lang, keepLastKnownFileType); - const char* attribute = keepLastKnownFileType ? - "lastKnownFileType" : - "explicitFileType"; - fileRef->AddAttribute(attribute, - this->CreateString(sourcecode.c_str())); - } + fileRef->AddAttribute(useLastKnownFileType? "lastKnownFileType" + : "explicitFileType", + this->CreateString(fileType)); // Store the file path relative to the top of the source tree. std::string path = this->RelativeToSource(fullpath.c_str()); From a339ea652952666182d2e63ddce088d023e2a5f5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 May 2014 13:50:53 -0400 Subject: [PATCH 2/2] Xcode: Add source file property to control file type (#14854) Add source file properties to control Xcode file type attributes: XCODE_EXPLICIT_FILE_TYPE => explicitFileType XCODE_LAST_KNOWN_FILE_TYPE => lastKnownFileType Add a RunCMake.XcodeProject test to verify generated project content. --- Help/manual/cmake-properties.7.rst | 2 ++ Help/prop_sf/XCODE_EXPLICIT_FILE_TYPE.rst | 8 ++++++ Help/prop_sf/XCODE_LAST_KNOWN_FILE_TYPE.rst | 9 +++++++ Help/release/dev/xcode-file-type.rst | 7 +++++ Source/cmGlobalXCodeGenerator.cxx | 27 ++++++++++++++----- Source/cmGlobalXCodeGenerator.h | 6 +++-- Tests/RunCMake/CMakeLists.txt | 4 +++ Tests/RunCMake/XcodeProject/CMakeLists.txt | 3 +++ .../RunCMake/XcodeProject/RunCMakeTest.cmake | 3 +++ .../XcodeProject/XcodeFileType-check.cmake | 10 +++++++ .../RunCMake/XcodeProject/XcodeFileType.cmake | 4 +++ Tests/RunCMake/XcodeProject/main.c | 0 Tests/RunCMake/XcodeProject/src-default | 0 Tests/RunCMake/XcodeProject/src-explicit | 0 Tests/RunCMake/XcodeProject/src-lastKnown | 0 15 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 Help/prop_sf/XCODE_EXPLICIT_FILE_TYPE.rst create mode 100644 Help/prop_sf/XCODE_LAST_KNOWN_FILE_TYPE.rst create mode 100644 Help/release/dev/xcode-file-type.rst create mode 100644 Tests/RunCMake/XcodeProject/CMakeLists.txt create mode 100644 Tests/RunCMake/XcodeProject/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodeFileType-check.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodeFileType.cmake create mode 100644 Tests/RunCMake/XcodeProject/main.c create mode 100644 Tests/RunCMake/XcodeProject/src-default create mode 100644 Tests/RunCMake/XcodeProject/src-explicit create mode 100644 Tests/RunCMake/XcodeProject/src-lastKnown diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 14d2e7fa3..3036a5f0e 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -289,6 +289,8 @@ Properties on Source Files /prop_sf/OBJECT_OUTPUTS /prop_sf/SYMBOLIC /prop_sf/WRAP_EXCLUDE + /prop_sf/XCODE_EXPLICIT_FILE_TYPE + /prop_sf/XCODE_LAST_KNOWN_FILE_TYPE Properties on Cache Entries =========================== diff --git a/Help/prop_sf/XCODE_EXPLICIT_FILE_TYPE.rst b/Help/prop_sf/XCODE_EXPLICIT_FILE_TYPE.rst new file mode 100644 index 000000000..1b24701a3 --- /dev/null +++ b/Help/prop_sf/XCODE_EXPLICIT_FILE_TYPE.rst @@ -0,0 +1,8 @@ +XCODE_EXPLICIT_FILE_TYPE +------------------------ + +Set the Xcode ``explicitFileType`` attribute on its reference to a +source file. CMake computes a default based on file extension but +can be told explicitly with this property. + +See also :prop_sf:`XCODE_LAST_KNOWN_FILE_TYPE`. diff --git a/Help/prop_sf/XCODE_LAST_KNOWN_FILE_TYPE.rst b/Help/prop_sf/XCODE_LAST_KNOWN_FILE_TYPE.rst new file mode 100644 index 000000000..42e37574d --- /dev/null +++ b/Help/prop_sf/XCODE_LAST_KNOWN_FILE_TYPE.rst @@ -0,0 +1,9 @@ +XCODE_LAST_KNOWN_FILE_TYPE +-------------------------- + +Set the Xcode ``lastKnownFileType`` attribute on its reference to a +source file. CMake computes a default based on file extension but +can be told explicitly with this property. + +See also :prop_sf:`XCODE_EXPLICIT_FILE_TYPE`, which is preferred +over this property if set. diff --git a/Help/release/dev/xcode-file-type.rst b/Help/release/dev/xcode-file-type.rst new file mode 100644 index 000000000..6f637f771 --- /dev/null +++ b/Help/release/dev/xcode-file-type.rst @@ -0,0 +1,7 @@ +xcode-file-type +--------------- + +* The :generator:`Xcode` generator learned to check source + file properties :prop_sf:`XCODE_EXPLICIT_FILE_TYPE` and + :prop_sf:`XCODE_LAST_KNOWN_FILE_TYPE` for a custom Xcode + file reference type. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index ac75fc233..e5fc4365b 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -647,13 +647,14 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( const std::string &fullpath, cmTarget& cmtarget, - const std::string &lang) + const std::string &lang, + cmSourceFile* sf) { // Using a map and the full path guarantees that we will always get the same // fileRef object for any given full path. // cmXCodeObject* fileRef = - this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang); + this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang, sf); cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); buildFile->SetComment(fileRef->GetComment()); @@ -696,7 +697,7 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); cmXCodeObject* buildFile = - this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang); + this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang, sf); cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject(); cmXCodeObject* settings = @@ -828,7 +829,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( const std::string &fullpath, cmTarget& cmtarget, - const std::string &lang) + const std::string &lang, + cmSourceFile* sf) { std::string fname = fullpath; cmXCodeObject* fileRef = this->FileRefs[fname]; @@ -850,6 +852,19 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( bool useLastKnownFileType = false; std::string fileType; + if(sf) + { + if(const char* e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) + { + fileType = e; + } + else if(const char* l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) + { + useLastKnownFileType = true; + fileType = l; + } + } + if(fileType.empty()) { // If fullpath references a directory, then we need to specify // lastKnownFileType as folder in order for Xcode to be able to @@ -902,7 +917,7 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); return this->CreateXCodeFileReferenceFromPath( - sf->GetFullPath(), cmtarget, lang); + sf->GetFullPath(), cmtarget, lang, sf); } //---------------------------------------------------------------------------- @@ -1052,7 +1067,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, { std::string obj = *oi; cmXCodeObject* xsf = - this->CreateXCodeSourceFileFromPath(obj, cmtarget, ""); + this->CreateXCodeSourceFileFromPath(obj, cmtarget, "", 0); externalObjFiles.push_back(xsf); } } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 23616b4f9..c9937edf3 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -163,10 +163,12 @@ private: std::vector& generators); cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string &fullpath, cmTarget& cmtarget, - const std::string &lang); + const std::string &lang, + cmSourceFile* sf); cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string &fullpath, cmTarget& cmtarget, - const std::string &lang); + const std::string &lang, + cmSourceFile* sf); cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf, cmTarget& cmtarget); cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 7f6ebf103..3eeda2f32 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -123,6 +123,10 @@ if("${CMAKE_GENERATOR}" MATCHES "Visual Studio [^6]") add_RunCMake_test(SolutionGlobalSections) endif() +if(XCODE_VERSION AND NOT "${XCODE_VERSION}" VERSION_LESS 3) + add_RunCMake_test(XcodeProject) +endif() + add_RunCMake_test(File_Generate) add_RunCMake_test(ExportWithoutLanguage) add_RunCMake_test(target_link_libraries) diff --git a/Tests/RunCMake/XcodeProject/CMakeLists.txt b/Tests/RunCMake/XcodeProject/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake new file mode 100644 index 000000000..8e4026ba0 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(XcodeFileType) diff --git a/Tests/RunCMake/XcodeProject/XcodeFileType-check.cmake b/Tests/RunCMake/XcodeProject/XcodeFileType-check.cmake new file mode 100644 index 000000000..7882d7f13 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeFileType-check.cmake @@ -0,0 +1,10 @@ +set(expect-default "explicitFileType = sourcecode") +set(expect-explicit "explicitFileType = \"sourcecode.c.h\"") +set(expect-lastKnown "lastKnownFileType = \"sourcecode.c.h\"") +foreach(src default explicit lastKnown) + file(STRINGS ${RunCMake_TEST_BINARY_DIR}/XcodeFileType.xcodeproj/project.pbxproj actual-${src} + REGEX "PBXFileReference.*src-${src}") + if(NOT actual-${src} MATCHES "${expect-${src}}") + message(SEND_ERROR "src-${src} does not match '${expect-${src}}':\n ${actual-${src}}") + endif() +endforeach() diff --git a/Tests/RunCMake/XcodeProject/XcodeFileType.cmake b/Tests/RunCMake/XcodeProject/XcodeFileType.cmake new file mode 100644 index 000000000..7faa78151 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeFileType.cmake @@ -0,0 +1,4 @@ +enable_language(C) +add_executable(main main.c src-default src-explicit src-lastKnown) +set_property(SOURCE src-explicit PROPERTY XCODE_EXPLICIT_FILE_TYPE sourcecode.c.h) +set_property(SOURCE src-lastKnown PROPERTY XCODE_LAST_KNOWN_FILE_TYPE sourcecode.c.h) diff --git a/Tests/RunCMake/XcodeProject/main.c b/Tests/RunCMake/XcodeProject/main.c new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/XcodeProject/src-default b/Tests/RunCMake/XcodeProject/src-default new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/XcodeProject/src-explicit b/Tests/RunCMake/XcodeProject/src-explicit new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/XcodeProject/src-lastKnown b/Tests/RunCMake/XcodeProject/src-lastKnown new file mode 100644 index 000000000..e69de29bb