精华内容
下载资源
问答
  • linux下动态库.so文件.a文件是否是独立可用的? 比如我有个dynamic.sostatic.o文件,这两个文件是否可能依赖于别的soa文件,甚至有没有可能依赖于.cpp/.c文件,或者只可能依赖其中的一种?即soa文件是否一定...
  • 动态分配和静态分配

    千次阅读 2019-06-28 21:06:11
    动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。 例如我们定义一个float型数组:float score[100]; 但是,在使用数组的...

    所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。

    例如我们定义一个float型数组:float score[100]; 但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?

    在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道我们要定义的这个数组到底有多大,那么你就要把数组定义得足够大。这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。即使你知道你想利用的空间大小,但是如果因为某种特殊原因空间利用的大小有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。

    这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。

    我们用动态内存分配就可以解决上面的问题. 所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于静态内存分配的特点:

    1、不需要预先分配存储空间;

    2、分配的空间可以根据程序的需要扩大或缩小。

         说白了,内存的静态分配和动态分配的区别主要是两个:

           一是时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。

          二是空间不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数alloca()进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。    

           对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。

            一般,用static修饰的变量,全局变量位于静态数据区。函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。

    展开全文
  • 起因 理论功底 ...动态和静态库 ...静态和动态库如何构建加载 静态和动态库依赖关系 Xcode 项目结构 iOS 依赖管理事实上的标准 解决问题 制作动态
    • 起因

    • 理论功底

      • 动态库和静态库

        • 介绍

        • 静态库和动态库的区别

        • 举个例子, iOS 项目中使用 Embeded Framework

        • 静态库和动态库如何构建和加载

        • 静态库和动态库依赖关系

      • Xcode 项目结构

        • iOS 依赖管理事实上的标准

      • 解决问题

        • 制作动态库

      • 剖析下动态库 Framework 吧

        • 回过头来看 Embened Framework

        • Why Swift does not Support Staic Libraies

        • CocoaPods 使用 Use_framework!

        • 动态库 Framework 的文件结构

          • 更愉快的导入文件

            资源问题

    • 参考

    起因

    去年,公司iOS端,之前由于所有的业务端代码都是混乱管理,造成开发有很多痛点无法单测,团队成员提交代码冲突机率大,CI配合效果差,功能性代码多端无法复用,单仓库代码量大,编译时间长 等等痛点,领导和组内多次沟通开始着手组件化开发,希望能改进这些开发中的痛点,成立组件化团队。

    组件化的方案大同小异,基础性代码封装私有库,业务组件交互交由中间件负责,项目依赖工具用iOS项目事实上的标准CocoaPods

    前期的基础性组件拆分都较为顺利,从依赖树的叶子节点开发是最合适的方案。

    随着组件抽离的越来越多,私有库的依赖体系也越来越复杂,慢慢过渡到了业务组件。业务组件用了Swift的第三方组件,用了Swift库的同学都知道必须加上use_frameworks!,这个标记是说Pod管理的依赖全部编译为动态库,然后呢我们的很多组件又依赖了诸如百度地图,微信分享等静态库,于是我在执行 pod install 报了一个没有碰见过的错误。

    1
    [!] The  'Pods-LJA_Example'  target has transitive dependencies that include static binaries:

    installError.png

    这就尴尬了,于是一阵疯狂的搜索google stackoverflow等,然而并没有什么卵用,而且上面催得急,根本没时间处理这些小问题 业务重构是最主要的,以至于我们的业务组件没有做到独立仓库拆分。

    直到最近终于找到了解决办法:( 主要是自己的功力不够深厚)

    理论功底

    动态库和静态库

    介绍

    首先静态库和动态库都是以二进制提供代码复用的代码库

    • 静态库 常见的是 .a

    • 动态库常见的是 .dll(windows),.dylib(mac),so(linux)

    • framework(in Apple): Framework 是Cocoa/Cocoa Touch程序中使用的一种资源打包方式,可以将代码文件、头文件、资源文件、说明文档等集中在一起,方便开发者使用。也就是说我们的 framework其实是资源打包的方式,和静态库动态库的本质是没有关系的

    静态库和动态库的区别

    静态库: 链接时会被完整的复制到可执行文件中,所以如果两个程序都用了某个静态库,那么每个二进制可执行文件里面其实都含有这份静态库的代码

    动态库: 链接时不复制,在程序启动后用dyld加载,然后再决议符号,所以理论上动态库只用存在一份,好多个程序都可以动态链接到这个动态库上面,达到了节省内存(不是磁盘是内存中只有一份动态库),还有另外一个好处,由于动态库并不绑定到可执行程序上,所以我们想升级这个动态库就很容易,windows和linux上面一般插件和模块机制都是这样实现的。

    But我们的苹果爸爸在iOS平台上规定不允许存在动态库,并且所有的 IPA 都需要经过苹果爸爸的私钥加密后才能用,基本你用了动态库也会因为签名不对无法加载,(越狱和非 APP store 除外)。于是就把开发者自己开发动态库掐死在幻想中。

    直到有一天,苹果爸爸的iOS升级到了8,iOS出现了APP Extension,swift编程语言也诞生了,由于iOS主APP需要和Extension共享代码,Swift语言的机制也只能有动态库,于是苹果爸爸尴尬了,不过这难不倒我们的苹果爸爸,毕竟我是爸爸,规则是我来定,我想怎样就怎样,于是提出了一个概念Embedded Framework,这种动态库允许APP和APP Extension共享代码,但是这份动态库的生命被限定在一个APP进程内。简单点可以理解为被阉割的动态库。

    举个例子,iOS项目中使用Embeded Framework

    如果你把某个自己开发的动态库(系统的不算,毕竟苹果是爸爸)放在了Linked Frameworks and Libraries里面,程序一启动就会报Reason: Image Not Found,你只能把它放在Embeded Binaries里面才能正常使用,

    看图: 

    useEmbededFramework.png

    静态库和动态库如何构建和加载

    简单点,说话的方式简单点~~

    上面的介绍貌似有点抽象啊套用在美团技术分享大会上的话就是:

    • 静态库: 一堆目标文件(.o/.obj)的打包体(并非二进制文件)

    • 动态库: 一个没有main函数的可执行文件

    这里我们来复习下C语言的基本功,编译和链接

    • 编译: 将我们的源代码文件编译为目标文件

    • 链接: 将我们的各种目标文件加上一些第三方库,和系统库链接为可执行文件。

    由于某个目标文件的符号(可以理解为变量,函数等)可能来自其他目标文件,其实链接这一步最主要的操作就是决议符号的地址。

    • 若符号来自静态库(本质就是.o 的集合包)或 .o,将其纳入链接产物,并确定符号地址

    • 若符号来自动态库,打个标记,等启动的时候再说---交给dyld去加载和链接符号

    于是链接加装载就有了不同的情况

    • Load 装载:将库文件载入内存

        Static Loading:启动时

        Dynamic Loading:启动后(使用时)

    • Link 链接:决议符号地址

        Static Linking:构建(链接)时

        Dynamic Linking:运行时(启动时或使用时)

    然后组合起来就是 2 * 2 = 4 了

    • Static Loading + Static Linking

    • Static Loading + Dynamic Linking

    • Dynamic Loading + Dynamic Linking

    • ~~Dynamic Loading + Static Linking~~

    第一种是纯静态库相关了

    第二种就是静态加载(启动时),动态链接,链接时,动态库参与链接,但是这时候只是给符号打了标记告诉我这个符号来自与动态库,程序启动时,iOS或者Mac OS操作系统的dyld自动load + link。

    既然全部都是自动的。那么符号的调用方完全不知道你到底是源码还是静态库,动态库 。

    第三种收到调用dlopen + performSelector通常iOS的APP不适用这里不讨论

    第四种,没见过,个人也不是特别懂

    有需求请参看文后的程序员的自我修养一书

    静态库和动态库依赖关系

    既然有 2 种库,那么依赖关系又是 2 * 2 喽

    • libA.a dependency libB.a

    • UIKit.dylib dependency Foundation.dylib

    • libA.a dependency Foundation.dylib

    • MyXX.dylib dependency libA.a

    第一种 静态库互相依赖,这种情况非常常见,制作静态库的时候只需要有被依赖的静态库头文件在就能编译出来。但是这就意味者你要收到告诉使用者你的依赖关系

    幸运的是CocoaPod就是这样做的

    第二种动态库依赖动态库,两个动态库是相互隔离的具有隔离性,但是制作的静态库的时候需要被依赖动态库参与链接,但是具体的符号决议交给dyld来做。

    第三种,静态库依赖动态库,也很常见,静态库制作的时候也需要动态库参与链接,但是符号的决议交给dyld来做。

    第四种,动态库依赖静态库,这种情况就有点特殊了。首先我们设想动态库编译的时候需要静态库参与编译,但是静态库交由dyld来做符号决议,but这和我们前面说的就矛盾了啊。静态库本质是一堆.o 的打包体,首先并不是二进制可执行文件,再者你无法保证主程序把静态库参与链接共同生成二进制可执行文件。这就尴尬了。

    怎么办?

    目前的编译器的解决办法是,首先我无法保证主程序是否包含静态库,再者静态库也无法被dyld加载,那么我直接把你静态库的.o 偷过来,共同组成一个新的二进制。也被称做吸附性

    那么我有多份动态库都依赖同样的静态库,这就尴尬了,每个动态库为了保证自己的正确性会把静态库吸附进来。然后两个库包含了同样的静态库,于是问题就出现了。 看到这里想必前面出现的错误你已经能猜出来了把~_~

    后面再详细解释

    先来个总结

    可执文件(主程序或者动态库)在构建的链接阶段

    • 遇到静态库,吸附进来

    • 遇到动态库,打标记,彼此保持独

    Xcode 项目结构

    • target:对于一个产物(app,.a ,.framework)

    • project:一个项目包含多个 target

    • workspace: 一个包含多个 target

    • schema: 指定了一个产物是按照何种的依赖关系,编译-链接到最终的一个产物

    iOS 依赖管理事实上的标准

    这么多年,Apple的博客和文档也就告诉了我们什么是静态库什么是动态库,如何制作等。但是并没有给我们提供一系列的依赖管理工具。所以CocoaPods成了事实上的标准。

    通常CocoaPods管理的工程结构如下:

    QQ截图20170427095936.png

    那么当我们按下CMD + B的时候,整个项目按照先编译被依赖Pod,然后依赖其他Pod的Pod也被构建出来,最终所有的组件被编译为一个lib-Pods-XXXAPP.a被添加进项目进去。资源通过CocoaPods提供的脚本也一并被复制进去。想了解CocoaPods做了什么的读者可以参看后面的链接

    解决问题

    这么多理论功底的建立,相信我们已经能分析出来之前pod install的原因了。就是用了use_framework那么我们的所有Pod都会以动态库(Embeded Framework)的形式去构建,于是那些非开源的库(如百度地图,微信分享)如果被多个Pod依赖(组件化开发中太常见了)于是被吸附到动态库里面,所以CocoaPod直接就不让我们install成功。因为你现在的依赖管理就是错误的。

    在听取美团叶樉老师分享的时候 他们的出发点是因为要绕过苹果爸爸在iOS9以下对__text 段60M的限制使用了动态库方案,我们是因为某些swift库必须要用到(历史遗留原因)动态库。美团的做法是摘除依赖关系,自定义CocoaPods(开源的本来就是用着不爽我就改)。但是我是个小菜鸡啊。我也不会 ruby(以后会学的),但是叶樉老师给我提了别的idea。前面我们知道 动态库和动态库是隔离性,动态库依赖静态库具有吸附性,那么我们可以自定义一个动态库把百度地图这种静态库吸附进来。对外整体呈现的是动态库特性。其他的组件依赖我们自定义的动态库,由于隔离性的存在,不会出现问题。

    制作动态库

    1 创建动态库项目这里以 wx 举例

    createDynamicFramework.png

    2 按照微信的官方文档。添加依赖库(我是因为pod install巨慢所以我直接拽进来了)

    wxDdependency.png

    3 将wx的PublicHeader暴露出来,注意由于我并没有使用到wx相关API所以链接器帮我们链接动态库的时候可能并不会把wx静态库吸附进来。我们手动在build Setting的other link flags加上-all_load标记

    publicHeader.png

    4.在Schema里面跳转编译配置为Release,并且选择所有的CPU架构

    SchemaRelease.png

    buildArchive.png

    5 然后选择模拟器或者 Generic iOS Device 运行编译就会生成对应版本的 Framework 了。

    releaseFrameworl.png

    6.但是为了保证开发者使用的时候是真机模拟器都能正常使用,我们需要合并不同架构

    这里在Build Phases里添加以下脚本,真机和模拟器都Build一遍之后就会在工程目录下生成Products文件夹,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    if  "${ACTION}"  "build"  ]
    then
    INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
    DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
    SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
    if  [ -d  "${INSTALL_DIR}"  ]
    then
    rm -rf  "${INSTALL_DIR}"
    fi
    mkdir -p  "${INSTALL_DIR}"
    cp -R  "${DEVICE_DIR}/"  "${INSTALL_DIR}/"
    #ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
    lipo -create  "${DEVICE_DIR}/${PROJECT_NAME}"  "${SIMULATOR_DIR}/${PROJECT_NAME}"  -output  "${INSTALL_DIR}/${PROJECT_NAME}"
    open  "${DEVICE_DIR}"
    open  "${SRCROOT}/Products"
    fi

    fatframework.png

    于是我们有了我们自己的私有动态库LJWXSDK,那么我们来验证我们之前的问题

    首先指定一个LJWXSDK.podspec这里我直接传到了我的Github上面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #
    # Be sure to run `pod lib lint LJPod.podspec' to ensure this is a
    # valid spec before submitting.
    #
    # Any lines starting with a # are optional, but their use is encouraged
    # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
    #
    Pod:: Spec. new  do  |s|
       s.name             =  'LJWXSDK'
       s.version          =  '0.1.0'
       s.summary          =  'A short description of LJWXSDK.'
       s.description      = <  'MIT' , : file =>  'LICENSE'  }
       s.author           = {  'ValiantCat'  =>  '519224747@qq.com'  }
       s.source = { : http  =>  'http://onk2m6gtu.bkt.clouddn.com/LJWXSDK.framework.zip'  }
       s.ios.deployment_target =  '8.0'
       s.default_subspec =  'zip'
       s.subspec  'zip'  do  |zip|
       
         puts  '-------------------------------------------------------------------'
         puts  'Notice: LJWXSDK is zip now'
         puts  '-------------------------------------------------------------------'
         zip.ios.vendored_frameworks =  '*.framework'
       end
    end

    注意上面我是把二进制压缩丢进了七牛的 oss 文件存储。毕竟免费还快。

    然后通过 pod lib create 创建了一个 pod 用来验证之前我们的传递性依赖问题,

    文件夹结构如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    .
    ├── Example
    │   ├── LJA
    │   │   ├── Base.lproj
    │   │   │   ├── LaunchScreen.storyboard
    │   │   │   └── Main.storyboard
    │   │   ├── Images.xcassets
    │   │   │   └── AppIcon.appiconset
    │   │   │       └── Contents.json
    │   │   ├── LJA-Info.plist
    │   │   ├── LJA-Prefix.pch
    │   │   ├── LJAppDelegate.h
    │   │   ├── LJAppDelegate.m
    │   │   ├── LJViewController.h
    │   │   ├── LJViewController.m
    │   │   ├── en.lproj
    │   │   │   └── InfoPlist.strings
    │   │   └── main.m
    │   ├── LJA.xcodeproj
    │   ├── LJA.xcworkspace
    │   ├── Podfile
    │   ├── Podfile.lock
    │   ├── Pods
    │   │   ├── Headers
    │   │   ├── LJWXSDK
    │   │   │   └── LJWXSDK.framework
    │   │   │       ├── Headers
    │   │   │       │   ├── LJWXSDK.h
    │   │   │       │   ├── WXApi.h
    │   │   │       │   ├── WXApiObject.h
    │   │   │       │   └── WechatAuthSDK.h
    │   │   │       ├── Info.plist
    │   │   │       ├── LJWXSDK
    │   │   │       ├── Modules
    │   │   │       │   └── module.modulemap
    │   │   │       ├── _CodeSignature
    │   │   │       │   └── CodeResources
    │   │   │       └── read_me.txt
    │   │   ├── Local\ Podspecs
    │   │   │   ├── LJA.podspec.json
    │   │   │   ├── LJB.podspec.json
    │   │   │   └── LJWXSDK.podspec.json
    │   │   ├── Manifest.lock
    │   │   ├── Pods.xcodeproj
    │   │   │   ├── project.pbxproj
    │   │   │   ├── project.xcworkspace
    │   │   ├── Target\ Support\ Files
    │   │   │   ├── LJA
    │   │   │   │   ├── Info.plist
    │   │   │   │   ├── LJA-dummy.m
    │   │   │   │   ├── LJA-prefix.pch
    │   │   │   │   ├── LJA-umbrella.h
    │   │   │   │   ├── LJA.modulemap
    │   │   │   │   └── LJA.xcconfig
    │   │   │   ├── LJB
    │   │   │   │   ├── Info.plist
    │   │   │   │   ├── LJB-dummy.m
    │   │   │   │   ├── LJB-prefix.pch
    │   │   │   │   ├── LJB-umbrella.h
    │   │   │   │   ├── LJB.modulemap
    │   │   │   │   └── LJB.xcconfig
    │   │   │   ├── Pods-LJA_Example
    │   │   │   │   ├── Info.plist
    │   │   │   │   ├── Pods-LJA_Example-acknowledgements.markdown
    │   │   │   │   ├── Pods-LJA_Example-acknowledgements.plist
    │   │   │   │   ├── Pods-LJA_Example-dummy.m
    │   │   │   │   ├── Pods-LJA_Example-frameworks.sh
    │   │   │   │   ├── Pods-LJA_Example-resources.sh
    │   │   │   │   ├── Pods-LJA_Example-umbrella.h
    │   │   │   │   ├── Pods-LJA_Example.debug.xcconfig
    │   │   │   │   ├── Pods-LJA_Example.modulemap
    │   │   │   │   └── Pods-LJA_Example.release.xcconfig
    │   │   │   └── Pods-LJA_Tests
    │   │   │       ├── Info.plist
    │   │   │       ├── Pods-LJA_Tests-acknowledgements.markdown
    │   │   │       ├── Pods-LJA_Tests-acknowledgements.plist
    │   │   │       ├── Pods-LJA_Tests-dummy.m
    │   │   │       ├── Pods-LJA_Tests-frameworks.sh
    │   │   │       ├── Pods-LJA_Tests-resources.sh
    │   │   │       ├── Pods-LJA_Tests-umbrella.h
    │   │   │       ├── Pods-LJA_Tests.debug.xcconfig
    │   │   │       ├── Pods-LJA_Tests.modulemap
    │   │   │       └── Pods-LJA_Tests.release.xcconfig
    │   │   └── libWeChatSDK
    │   │       ├── README.md
    │   │       ├── WXApi.h
    │   │       ├── WXApiObject.h
    │   │       ├── WechatAuthSDK.h
    │   │       └── libWeChatSDK.a
    ├── LICENSE
    ├── LJA
    │   ├── Assets
    │   └── Classes
    │       └── LJA.m
    ├── LJA.podspec
    ├── LJB
    │   ├── Assets
    │   └── Classes
    │       └── LJB.m
    ├── LJB.podspec
    ├── README.md
    └── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj

    testframework.pngdependencyDynamicLibrary.png

    useDynamicFramework.png

    测试工程我也丢在7牛上面。下载测试即可

    编译运行。完美。我们又可以愉快的和swift第三方库配合使用。

    很多人可能会问 诸如百度地图 微信这种sdk为什么官方不支持动态库版(所说的都是embeded Framework),猜测是为了兼容更低iOS7版本吧

    很多人会觉得麻烦的要死。首先每个公司多多少少都有历史包袱,麻烦也要做,再者这是一次对基本功的补充,即便你们没有用到,但是为了学习,这篇教程所做的也值得你尝试一次。

    剖析下动态库 Framework 吧

    上述解决了我们一开始遇到的问题。but既然动态库和静态库压根就不一回事,所以里面还是有很多细节值得我们去了解的。

    回过头来看 Embened Framework

    首先我们之前记得如果一个动态库加在LinkedFrameworksand Libraies程序启动就会报ImageNotFound,如果放在EmbededBinaries里面就可以。这是为什么呢。我们拿MacoView来看下两种情况下可执行文件的细节

    loadEmbededFramework.png

    loadSystemFramework.png

    appContentFiles.png

    其中@rpth 这个路径表示的位置可以查看Xcode中的链接路径问题

    这样我们就知道了其实加在EmbededBinaries里面的东西其实会被复制一份到xx.app里面,所以这个名字起得还是不错的直译就是嵌入的框架

    Why Swift does not Support Staic Libraies

    造成这个的主要原因是Swift的运行时库(不等同于OC的runtime概念),由于Swift的ABI不稳定,静态库会导致最终的目标程序中包含重复的运行库,相关可以看下最后的参考文章SwiftInFlux#static-libraries。等到我们的SwiftABI稳定之后,我们的静态库支持可能就又会出现了。当然也可能不出Swift伴随诞生的SPM(Swift,Package Manager),可能有更好的官方的包依赖管理工具。让我们期待吧。

    CocoaPods使用Use_framework!

    既然加了Swift的第三方库之后就需要在Podfile里面加上use_framework! 那么CocoaPods就会帮我们生成动态库,但是奇怪的是,我们并没有在主工程的embeded binaries看到这个动态库,这又是什么鬼。其实是CocoaPods使用脚本帮我们加进去了。脚本位置在主工程的build Phase下的Emded Pods frameworks

    1
    "${SRCROOT}/Pods/Target Support Files/Pods-LJA_Example/Pods-LJA_Example-frameworks.sh"

    动态库Framework的文件结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .
    ├── Headers
    │   ├── LJWXSDK.h
    │   ├── WXApi.h
    │   ├── WXApiObject.h
    │   └── WechatAuthSDK.h
    ├── Info.plist
    ├── LJWXSDK
    ├── Modules
    │   └── module.modulemap
    └── _CodeSignature
         └── CodeResources
    • Headers 一般是头文件。非private里面的头文件都会在里面

    • info.plist 配置信息,不深究

    • Modules 这个文件夹里有个module.modulemap文件,后面在讲解

    • 二进制文件,这就是上面提到的不带main的二进制文件了,.o 的打包体

    • _codeSignature签名文件 (苹果爸爸的约束)

    • more资源文件。这里暂时没用到,所以没有 ,但是这个也是个大坑

    更愉快的导入文件

    • @class,@protocol:不说了就是声明一个类,并不导入。

    • #import <>, #import"":是加强版的#include<>,#include"" 防止重复导入的。

    • #import<> : 通过build setting里面中的header Search Path里面去找

    • #import"" : 第一步先搜索user Header search Path再搜索 header search Path 。所以对我们的framework来说,CocoaPod帮我们加到了Header search Path目前2种导入方式都是可以支持的。

    上面的导入方式都带了 某个framework的路径"xx/xx.h" ,我们在开发自己主工程的时候会发现我们导入主工程其他类是不需要导入前缀的。 这又是怎么回事。

    看下面的配置

    no-recursive.png

    目前的配置是non-recursive。如果把non去掉意思就是我可以递归的去查找某些framework下面的头文件了。 但是Xcode的效率肯定就会有影响。

    还是不建议修改的好。

    大家都知道iOS7之后多了@import,这又是什么鬼。

    简单理解这个方式叫做Module导入,好处就是使用了@import 之后不需要在project setting手动添加framework,系统会自动加载,而且效率更高。

    最主要的是swift也只能这样用。

    导入的时候系统会查找如果有模块同名的文件就会导入这个文件。如果没有CocoaPods帮我们生成一个module-umbrela.hl文件,然后就是导入的这个文件。

    回过头来看我们的framework的结构 里面有个Modules文件夹,里面有个文件module.modulemap

    1
    2
    3
    4
    5
    6
    framework module LJWXSDK {
       umbrella header  "LJWXSDK.h"
     
       export *
       module * { export * }
    }

    我们可以看到其实被暴露的header就是这个文件,之前我在按照#import "/"的时候有个警告

    missSubModule.png

    而且按照@import 导入的东西发现没有导入可用的头文件就是因为并没有在umbrella header的头文件中加入其他头文件。

    加入之后我们就可以完美的使用@import ,并且#import"/" 也不会报warning

    更多关于umbrella Header 参看文后参考

    资源问题

    首先我们来看常见的资源文件: 主要分为图片和其他类资源那么加载图片和加载其他资源都是怎么做的?

    1: [UIimage imageNamed:]

    2: [NSbundle bundleForclass[XXX class]]

    其实方式1去本质就是去mainBundle去拿资源,方式2从XXX所在的框架里面去拿。

    前面也说道framework只是资源的打包方式,本质上是有两种的。

    我们这个framework如果本质是静态库,那么无需改变使用方式,资源最终都会打包到Main Bundle里面

    如果我们这个framework本质是动态库,那么我们的资源就发生了变化,资源就会被存放在framework里面。所以我们需要使[NSbundle bundleForclass[XXX class]]。需要注意的是很多人为了简单,下意

    的使用self class传递,但是有可能这个self实例不在资源所属的framework。所以会出现资源加载失败。一定要谨慎使用。

    展开全文
  • 动态变量和静态变量的区别

    千次阅读 2015-10-03 10:13:01
    动态变量和静态变量的区别:1、存储位置动态变量:存储在内存出栈数据区静态变量:存储在全局数据区(静态数据区)2、生命期动态变量:根据你定义的位置确定,比如你在一个函数中定义的,那么超出该函数范围变量将...

    动态变量和静态变量的区别:

    1、存储位置

    动态变量:存储在内存出栈数据区

    静态变量:存储在全局数据区(静态数据区)

    2、生命期

    动态变量:根据你定义的位置确定,比如你在一个函数中定义的,那么超出该函数范围变量将失效

    静态变量:程序结束时才释放

    3、作用域

    动态变量:同样的要根据你定义的位置才能确定,和第二点的一样

    静态变量:当前文件中有效

    展开全文
  • ubuntu18.04配置静态ip和动态ip

    万次阅读 多人点赞 2019-03-18 18:43:38
    今天需要使用ubuntu系统作项目了,发现问题来了...现在问题来了,如何恢复成动态ip呢? 自己算是取巧了吧,查看的是如何配置静态ip,照着里面原始的ip配置,恢复了动态ip。 1. ubuntu18.04配置静态ip 注意: 18.04...
    • 今天需要使用ubuntu系统做项目了,发现问题来了:所使用的主机(ubuntu18.04)之前是配置好的静态ip,现在实验室响应学校信息中心的号召,使用单人账号登陆了,每个人独享自己的20M带宽,网速溜得一匹。现在问题来了,如何恢复成动态ip呢?
    • 自己算是取巧了吧,查看的是如何配置静态ip,照着里面原始的ip配置,恢复了动态ip。

    1. ubuntu18.04配置静态ip

    注意: 18.04和16.04不一样了,配置静态ip的方法有很大差异!

    • 查找netplan目录下默认的网络配置文件,文件后缀为.yaml,我的是叫01-network-manager-all.yaml的文件。如果没有可以使用sudo gedit 01-network-manager-all.yam自己创建和。

      $ cd /etc/netplan
      $ ls
      

      在这里插入图片描述

    • 编辑网络配置文件之前,先查看自己的网卡名称,我的是enp3s0

      $ ifconfig
      

      在这里插入图片描述

    • 编辑网络配置文件01-network-manager-all.yaml,内容如下:

      # Let NetworkManager manage all devices on this system
      network:
        version: 2
        renderer: NetworkManager
        ethernets:
           enp3s0: #配置的网卡名称,使用ifconfig -a查看得到
             dhcp4: no #dhcp4关闭
             addresses: [192.168.202.36/24] #设置本机IP及掩码
             gateway4: 192.168.202.1 #设置网关
             nameservers:
               addresses: [192.168.202.1] #设置DNS
      
    • 使用命令,使静态ip生效。

      $ sudo netplan apply
      
    • 编辑网络配置文件之前,使用ifconfig命令查看配置情况,如果配置成功上图中ip会变成自己设置的ip。

    参考链接:

    2. ubuntu18.04配置动态ip

    • 查看网卡名称,参考上文。

    • 查找网络配置文件,参考上文。

    • 修改网络配置文件的内容如下:

      # Let NetworkManager manage all devices on this system
      network:
        version: 2
        renderer: NetworkManager
        ethernets:
           enp3s0: #配置的网卡名称,使用ifconfig -a查看得到
             dhcp4: true #dhcp4开启
             addresses: [] #设置本机IP及掩码,空
             optional: true
      
    • 使用$ sudo netplan apply命令,使动态生效。之后再使用ifconfig命令查看配置情况,如果配置成功上图中ip会变成动态的ip。

    参考链接:

    展开全文
  • 原来编译的时候都是用的很随意,没用系统的总结一下,这几天在编译的时候遇到一些...1.动态和静态库简介 静态库在程序链接的时候会自动的链接到程序里,所以一旦编译完成,静态库就不需要了,静态库以.a
  • Linux-动态链接与静态链接对比(动态和静态库)

    千次阅读 多人点赞 2017-12-14 17:52:46
    一、库的基础概念: 在windows平台linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。...按照库的使用方式又可分为动态和静态库,在不同平台下...
  • QT 动态和静态库的实现调用

    千次阅读 2018-05-23 12:34:55
    QT 动态和静态库的实现调用一、简述 加强某一部分代码的保密性,将其打包成动态库或静态库;或者是调用其他开源的库文件。二、效果三、工程结构四、源文件...
  • 详解Java动态绑定和静态绑定机制

    千次阅读 2019-04-22 09:27:42
    https://jiayouxujin.github.io/2019/04/20/java动态绑定和静态绑定详解/ 这一次,彻底搞懂动态绑定和静态绑定机制
  • 动态SQL 和静态SQL 的 区别

    千次阅读 2018-08-20 11:24:57
    所谓SQL的静态和动态,是指SQL语句在何时被编译和执行,二者都是用在SQL嵌入式编程中的,这里所说的嵌入式是指将SQL语句嵌入在高级语言中,而不是针对于单片机的那种嵌入式编程。 二者区别 : 静态SQL 动态SQL ...
  • 动态路由和静态路由

    千次阅读 2014-09-14 11:02:42
    静态路由  静态路由是由管理员在路由器中手动配置的固定路由,路由明确地指定了包到达目的地必须经过的路径,除非网络管理员干预,否则静态路由不会发生变化。静态路由不能对网络的改变作出反应,所以一般说静态...
  • hive动态分区和静态分区

    千次阅读 2019-05-05 11:06:15
    hive动态分区和静态分区 一)hive中支持两种类型的分区: 静态分区SP(static partition) 动态分区DP(dynamic partition) 静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断...
  • Unity3D中的动态字体和静态字体

    千次阅读 2019-02-26 02:54:12
    Unity3D中支持动态字体和静态字体两种格式字体,动态字体即使用TTF格式字体库,静态字体则需要自己打包字体图集。动态字体和静态字体区别在于,动态字体如果出现字体库中不存在的字体,会使用系统字体,而静态字体则...
  • Pytorch Note5 动态和静态动态和静态图TensorFlowPyTorch 动态和静态图 目前神经网络框架分为静态图框架和动态图框架,PyTorch TensorFlow、Caffe 等框架最大的区别就是他们拥有不同的计算图表现形式。 ...
  • 动态IP需要在连接网络时... 动态IP和静态IP对网速的影响  ISP对每个用户所提供的网速,并不是从IP地址限定的,而是从用户连接到ISP的物理线路上进行限定的。例如,ISP对小明家的线路开放了4M的带宽,但是对小红家...
  • 动态和静态库的区别

    千次阅读 2016-06-29 09:21:43
    库是共享程序代码的方式,一般分为静态和动态库。 静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次...
  • 动态vlan和静态vlan

    千次阅读 2018-11-27 15:21:37
    静态VLAN。静态VLAN也称为基于端口的VLAN,因为用户的主机属于哪个VLAN是根据交换机的端口属于哪个VLAN而定的。网络管理员首先把端口分配到不同的VLAN内,根据规划把用户的主机与相应的端口相连,这样就把...动态...
  • 神经网络——动态和静态

    千次阅读 2020-01-13 21:04:11
    目前神经网络框架分为静态图框架和动态图框架,PyTorchTensorFlow、Caffe等框架最大的区别就是他们拥有不同的计算图表现形式。TensorFlow1.*使用静态图(在TensorFlow2.*中使用的是动态图),这意味着我们先定义...
  • 本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的...②静态库libbb.a依赖动态库libaa.so的测试; ③动态库libbb.so依赖静态库libaa.a的测试; ④动态库libbb.so依赖动态库libaa.so的测试; ...
  • 动态绑定和静态绑定

    千次阅读 2017-12-11 20:04:53
    动态绑定动态绑定是指编译器在编译阶段不知道要调用哪个方法Parent父类,父类有两个方法一个是类方法shout,一个是实例方法saypublic class Parent { String name; public static void shout(){ System.out.println...
  • 通常我们所说的动态语言、静态语言指 动态类型语言(Dynamically Typed Language) 静态类型语言Statically Typed Language)。 还有一个 Dynamic Programming Language (动态编程语言),静态编程语言。 ...
  • 动态IP和静态IP的优缺点

    千次阅读 2020-12-07 11:18:37
    在使用代理IP的时候,我们通常会见到动态IP和静态IP这两种选择,IP地址作为我们访问网络的编号,每个人的IP都是不一样的。而获取的IP又可以分为动态IP和静态IP,那么动态IP和静态IP的优缺点都是什么呢?神龙IP一起...
  • 机器学习中常见的动态和静态

    万次阅读 2018-12-23 20:34:57
    在我们日常学习中总是听到动态和静态图的概念,今天就在这里做一个小总结,提醒自己. 目前神经网络框架分为静态图框架和动态图框架,PyTorch TensorFlow、Caffe 等框架最大的区别就是他们拥有不同的计算图表现...
  • linux动态编译和静态编译

    千次阅读 2017-11-27 19:50:22
    为了使用方便,可以把这两个函数接口定义为动态链接库或静态链接库。用动态链接库编译生成的 可执行文件需调用.so文件方可正常运行,灵活但稍显麻烦;用静态链接库编译生成的可执行文件可直 接运行,不用再调用...
  • 一下,什么 是动态页面,什么是静态页面,接着我们再来理解静态页面和动态页面中的静态和动态到底指的是什么? 静态Web页面 Web的基础是将Web页面从服务器传输到客户端。在最简单的形式中,W...
  • 动态链接和静态链接的区别

    千次阅读 2018-12-16 21:16:44
    动态链接和静态链接的区别 动态链接和静态链接的区别 https://www.cnblogs.com/njczy2010/p/5793477.html 一、分别编译与链接(Linking) 大多数高级语言都支持分别编译,程序员可以显式地把程序划分为独立的...
  • gcc 编译动态和静态

    千次阅读 2012-06-22 18:13:34
    Linux C 编程入门之一:gcc 编译动态和静态库cheungmine20121 准备工作Windows7+Cygwin+gcc在同一个目录下准备好下面3个文件,其中3-2,3-3用来生成动态库或静态库:主调用程序源代码3-1:main.c/** * main.c */ ...
  • 动态链接和静态链接

    千次阅读 2010-04-15 17:55:00
    理解静态链接和动态链接 前些日子在论坛上看到这样两个问题: 1、什么叫静态链接和动态链接?(static linking,dynamic linking) 2、如何理解先期迟后联编?(early binding,later binding) 3、连接时所需的库...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,062,025
精华内容 424,810
关键字:

动态问题和静态问题