修改Xcode配置使其支援建立編譯iphone上的dylib工程

來源:互聯網
上載者:User
此帖純粹討論怎樣更改xcode配置來使其支援建立iphone上的dylib工程檔案,不涉及任何其他破解話題!

測試機器:10.6 with Xcode3.2

最近在研究如何建立iphone上的dylib檔案,google出來的都是toolchain的東西,使用makefile來編譯的,像我這種習慣IDE的人來說非常之不爽,所以花了一天時間來破解了下Xcode來讓它可以建立編譯iphone上的dylib檔案的工程。

簡單說下分析思路吧

首先xcode支援建立iphone static libtary和Cocoa的dynamic linrary的工程,通過不同編譯對比可以發現Xcode通過productType = "com.apple.product-type.library.dynamic";配置來確定工程類型的。
開啟**.xcodeproj/project.pbxproj檔案,搜尋productType=定位,可以發現如所示的內容
[attachment=10545] 
可以建立一個iphone的static工程把static改成dynamic編譯看看,可以發現xcode提示不支援dynamic類型的工程,無法編譯,那我們讓他支援就好了。

我們需要修改以下檔案
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications/iPhoneOSProductTypes.xcspec
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications/iPhoneOSPackageTypes.xcspec
在iPhoneOSProductTypes.xcspec中添加下列片段

// Dynamic library
    {   Type = ProductType;
        Identifier = com.apple.product-type.library.dynamic;
        Class = PBXStaticLibraryProductType;
        Name = "Dynamic Library";
        Description = "Dynamic library";
        IconNamePrefix = "TargetLibrary";
        DefaultTargetName = "Dynamic Library";
        DefaultBuildProperties = {
            FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)";
            MACH_O_TYPE = "mh_dylib";
            REZ_EXECUTABLE = YES;
            EXECUTABLE_PREFIX = "";
            EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)";
            EXECUTABLE_EXTENSION = "dylib";
            PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include";
            PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include";
            INSTALL_PATH = "/usr/local/lib";
            DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)";
            LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
            DYLIB_COMPATIBILITY_VERSION = "1";
            DYLIB_CURRENT_VERSION = "1";
            FRAMEWORK_FLAG_PREFIX = "-framework";
            LIBRARY_FLAG_PREFIX = "-l";
            LIBRARY_FLAG_NOSPACE = YES;
            STRIP_STYLE = "debugging";
            GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
            CODE_SIGNING_ALLOWED = NO;
        };
        PackageTypes = (
            com.apple.package-type.mach-o-library   // default
        );
    },

在iPhoneOSPackageTypes.xcspec中添加下列片段

// Mach-O dynamic library
    {   Type = PackageType;
        Identifier = com.apple.package-type.mach-o-library;
        Name = "Mach-O Dynamic Library";
        Description = "Mach-O dynamic library";
        DefaultBuildSettings = {
            EXECUTABLE_PREFIX = "";
            EXECUTABLE_SUFFIX = ".dylib";
            EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
            EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
        };
        ProductReference = {
            FileType = compiled.mach-o.dylib;
            Name = "$(EXECUTABLE_NAME)";
            IsLaunchable = NO;
        };
    },

檔案附上,可以直接下載替換,替換/修改前做好備份
[attachment=10546]

現在再編譯應該不會提示工程不支援了,那麼剩下的就是改變其編譯選項了,就是libtool的參數問題。
我們需要修改下列檔案
/Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/Libtool.xcspec
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS Build System Support.xcplugin/Contents/Resources/iPhoneLinkerOptions.xcspec
在Libtool.xcspec中添加下列片段

{   Identifier = com.apple.pbx.linkers.libtooldynamic;
    Type = Linker;
    Class = PBXLinkerSpecificationLibtool;
    Name = "Libtool";
    Description = "Create a dynamic library using Apple Mach-O Librarian (libtool)";
    IsAbstract = Yes;       // This is an internal tool, so we keep it out of the user interface
    BinaryFormats = (mach-o);
    Architectures = (ppc, ppc7400, ppc7450, ppc970, ppc64, i386, x86_64);
    CommandLine = "$(LIBTOOL) -dynamic -arch_only $(arch) -compatibility_version $(DYLIB_COMPATIBILITY_VERSION) -current_version $(DYLIB_CURRENT_VERSION) [options] [special-args] -o $(OutputPath)";      // 'special-args' includes the input files
    RuleName = "Libtool $(OutputPath) $(variant) $(arch)";
    ExecDescription = "Create Dynamic Library $(OutputPath:file)";
    InputFileTypes = (
        compiled.mach-o.objfile
    );
    Outputs = (
        // We're a linker-like task, so we expect to be given an output path in 'OutputPath'.
        "$(OutputPath)"
    );
    CommandOutputParser = XCGccCommandOutputParser;
    Options = (
        // LIBTOOL
        {   Name = LIBTOOL;
            Type = Path;
            DefaultValue = "$(PLATFORM_DEVELOPER_BIN_DIR)/libtool";
        },

        // SDK
        {   Name = SDKROOT;
            Type = Path;
            CommandLineFlag = "-syslibroot";
            IsInputDependency = Yes;
        },

        // Search paths
        {   Name = LIBRARY_SEARCH_PATHS;
            Type = PathList;
            FlattenRecursiveSearchPathsInValue = Yes;   // causes any paths that have a '/**' suffix to be replaced with matching paths
            CommandLinePrefixFlag = "-L";
        },

        // Input file lists
        {   Name = __INPUT_FILE_LIST_PATH__;
            Type = Path;
            DefaultValue = "$(LINK_FILE_LIST_$(variant)_$(arch))";      // this is set up for us as a read-only property
            CommandLineFlag = "-filelist";
            IsInputDependency = Yes;
        },
        {   Name = auxiliary_file_lists;
            Type = PathList;
            CommandLineFlag = "-filelist";
            IsInputDependency = Yes;
        },

        // Various flags
        {   Name = ALL_OTHER_LIBTOOLFLAGS;
            Type = StringList;
            DefaultValue = "$(LD_FLAGS) $(SECTORDER_FLAGS) $(OTHER_LDFLAGS) $(OTHER_LDFLAGS_$(variant)) $(OTHER_LDFLAGS_$(arch)) $(OTHER_LDFLAGS_$(variant)_$(arch)) $(OTHER_LIBTOOLFLAGS) $(OTHER_LIBTOOLFLAGS_$(variant)) $(OTHER_LIBTOOLFLAGS_$(arch)) $(OTHER_LIBTOOLFLAGS_$(variant)_$(arch)) $(PRODUCT_SPECIFIC_LIBTOOLFLAGS)";
            CommandLinePrefixFlag = "";
        },
        {   Name = EXPORTED_SYMBOLS_FILE;
            Type = Path;
            Condition = "$(SEPARATE_SYMBOL_EDIT) == NO";
            CommandLineFlag = "-exported_symbols_list";
            IsInputDependency = Yes;
        },
        {   Name = UNEXPORTED_SYMBOLS_FILE;
            Type = Path;
            Condition = "$(SEPARATE_SYMBOL_EDIT) == NO";
            CommandLineFlag = "-unexported_symbols_list";
            IsInputDependency = Yes;
        },
        {   Name = AdditionalCommandLineArguments;
            Type = StringList;
            CommandLinePrefixFlag = "";
        },

        {   Name = MACOSX_DEPLOYMENT_TARGET;
            Type = String;
            SetValueInEnvironmentVariable = "MACOSX_DEPLOYMENT_TARGET";
        },
    );
},

在iPhoneLinkerOptions.xcspec中搜尋
BasedOn = "default:com.apple.pbx.linkers.libtool";
替換成
BasedOn = "default:com.apple.pbx.linkers.libtooldynamic";
這樣修改後編譯iphone的library工程師都會使用dynamic的參數來編譯,
注意:如果要編譯iphone static library這裡需要將libtooldynamic修改回libtool並重啟Xcode(唯一的小缺陷,應該可以通過hook xcode編譯設定函數來動態修改,很麻煩,需要很多時間去找到相應的方法,找了一會兒就沒高興繼續,先將就用吧)

做好以上工作後就可以建立並編譯iphone上dynamic library的工程了。
這裡附上工程和target模板檔案
[attachment=10547]
解壓此zip得到Cocoa Touch Dynamic Library檔案夾,將其放到
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Project Templates/Library/下面

[attachment=10548]
解壓此zip得到Dynamic Library.trgttmpl檔案,將其放到
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Target Templates/Cocoa Touch/下面

重啟Xcode就可以看到了,
[attachment=10549]  [attachment=10550] 

測試結果
[attachment=10551] 
使用otool查看編譯出來的dylib檔案
[attachment=10552] 

成功!
謹記!!!!!需要修改檔案來切換回編譯static library!!!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.