I can believe fly.

Thursday, March 17, 2016

iOS 静态代码分析

【问题类型】
1  retain和release的正确使用
2  未使用的实例变量
3  未初始化的变量
4  无法到达的代码路径
5  引用空指针
6  除0
7  类型不兼容
8  缺少dealloc
9  内存泄漏

【使用方式】
1. 使用xcodebuild ... clean build analyze  或者加上RUN_CLANG_STATIC_ANALYZER=YES
输出报告:各个模块会生成在自己的build目录下/Users/builder/Library/Developer/Xcode/DerivedData/YY2-ekfapvflopyuogfnccpmryrhzpbf/Build/Intermediates/Pods.build/Distribute-iphoneos/Pods-GTM.build/StaticAnalyzer/Pods/Pods-GTM/normal/armv7/Pods-GTM-dummy.plist  。但没找到解析后的html信息。试着带上CLANG_ANALYZER_OUTPUT_DIR,可以改变StaticAnalyzer的输出目录。

2. 在xcodebuild前使用scan-build
输出报告:可通过-o参数指定,然后基于它加上随机数自动生成CLANG_ANALYZER_OUTPUT_DIR = /data/DUOWAN_BUILD/mobile/mobile-ios_analyzer/checkReports/2014-03-05-173031-54544-1
命令格式:
Option Description
-oTarget directory for HTML report files. Subdirectories will be created as needed to represent separate "runs" of the analyzer. If this option is not specified, a directory is created in /tmp to store the reports.
-h
(or no arguments)
Display all scan-build options.
-k
--keep-going
Add a "keep on going" option to the specified build command.This option currently supports make and xcodebuild.
This is a convenience option; one can specify this behavior directly using build options.
-vVerbose output from scan-build and the analyzer. A second and third "-v" increases verbosity, and is useful for filing bug reports against the analyzer.
-VView analysis results in a web browser when the build command completes.
--use-analyzer Xcode
or
--use-analyzer [path to clang]
scan-build uses the 'clang' executable relative to itself for static analysis. One can override this behavior with this option by using the 'clang' packaged with Xcode (on OS X) or from the PATH.
说明:
1. 建议分析debug配置
2. 在模拟器进行
3. Don't sign code

例子:
$CLANG_HOME/scan-build -k -v -v --use-analyzer $CLANG_HOME/bin/clang -o ./clangScanBuildReports xcodebuild -workspace YY2.xcworkspace -scheme YY2 -configuration Debug -sdk iphonesimulator

3. jenkins集成 clang-scanbuild-plugin,需要设置Target/workspace/scheme/sdk/等信息
输出报告:/data/DUOWAN_BUILD/mobile/mobile-ios_analyzer/clangScanBuildReports/2014-03-05-165238-25536-1
说明:
1. 使用此插件需要配置Target或者scheme或者如果编译要求有workspace也要带上,如果应用多了,这些值信息不一样,要为每个配置不同的信息有点难维护。

【小知识】
1. xcode5默认的clang路径/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
2.  sudo ./set-xcode-analyzer --use-checker-build=$clang_path 可以重设xcode集成的clang  官方介绍:http://clang-analyzer.llvm.org/xcode.html
3. 使用sudo  ./set-xcode-analyzer 更改clang,如果要用回xcode,则直接使用--use-xcode-clang。如果使用--use-checker-build来指定xcode自带clang的路径,则你在xcodebuild前使用/opt/tools/checker/scan-build,过程数据是显示了CLANG_ANALYZER_EXEC = /opt/tools/checker/bin/clang,但在解析的过程还是直接使用了你指定xcode自带clang的路径。
4. 使用clang新版本解析会比使用xcode自带的clang找到更多的问题。
【FAQ】
问:使用xcodebuild可以添加RUN_CLANG_STATIC_ANALYZER=YES;问题:如何在jenkins显示解析的结果
答: 没找到如果使用xcodebuild来clang其完整的输出报告。想要集成jenkins显示解析结果:
1. 直接使用jenkins插件,然后增加构建步骤:Clang Scan-Build 


2. 如果不想配置Clang Scan-Build步骤,那么可以直接在原来xcodebuild的基础上加上scan-build,且输出报告指向jenkins插件能识别的目录./clangScanBuildReports

codesign fails with !use_frameworks

错误:▸ Building Pods/AFNetworking [(Release)]
⌦ Code Sign error: Provisioning profile does not match bundle identifier: The provisioning profile specified in your build settings (“100edututorhd_inhouse”) has an AppID of “com.100.enterprise.tutorstudenthd” which does not match your bundle identifier “org.cocoapods.AFNetworking”.

问题:Do I need to modify all the info.plist to match my AppID? Or is there a way to skip codesign for the frameworks?
解决:在podfile里加入以下配置关掉签名
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
      config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
      config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
    end
  end
end




Friday, August 14, 2015

Gradle构建Android应用

Gradle构建Android应用

Gradle 介绍

Gradle 基于DSL(领域特定语言)语法的自动化构建工具。其所有task可由Groovy代码控制,因此相对Maven那套标准性的流程或模板来说,Gradle会更加灵活,扩展性更强。

安装

  1. 下载 http://services.gradle.org/distributions/gradle-2.4-all.zip
  2. 解压到安装目录,例如/opt/tools/Gradle
  3. 添加GRADLE_HOME/bin to your PATH environment variable

简单build.gradle

buildscript {
    repositories {
    mavenCentral()
    }

    dependencies {
    classpath 'com.android.tools.build:gradle:1.1.3'
    }
}

apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"
}

wrapper

安装完后,在项目的当前目录下执行 gradle init wrapper
如果是在已有maven配置的项目,gradle会自动识别转换,但部分配置还需要自行修改。
负责人使用wrapper初始化环境,开发团员的其它成员就可以不用自己安装了。
自动生成gradlew,build.gradle,settings.gradle等文件和相关目录
$ ./gradlew build

Downloading https://services.gradle.org/distributions/gradle-2.3-bin.zip
建议:在gradle项目里,尽量使用gradlew来编译,它会自动下载对应的版本,这样团队的其他成员就不需要手动安装了且可以保持大家使用的版本一致。

映射目录 sourceSets

如果你的工程是Eclipse 结构,那在build.gradle需要映射目录处理
android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        androidTest.setRoot('tests')
    }
}

依赖管理

设置从公司私服nexus下载依赖库

repositories {
      maven {
             url "http://127.0.0.1/nexus/content/groups/public"
    }
}

引用本地的aar库

repositories {
    flatDir {
    dirs 'libs'
    }
}

dependencies {
    compile(name:'cards', ext:'aar')
}

依赖jar

dependencies {
     compile group: 'com.duowan.mobile.uauth', name: 'yyauth', version:'1.7'
}
}

依赖so

dependencies {
         classpath 'com.nabilhachicha:android-native-dependencies:0.1+'
}

native_dependencies {
    artifact 'com.duowan.mobile.uauth:yyauth:1.7:armeabi'
    artifact 'com.duowan.mobile.uauth:yyauth:1.7:armeabi-v7a'
}

忽略lint的警告

lintOptions {
    abortOnError false
}

版本号设置

defaultConfig {
    versionCode System.getenv("BUILD_NUMBER") as Integer ?: 0     // 如果环境变量BUILD_NUMBER存在则读取,否则取0
    versionName version                                                                       //  version是gradle.propertise定义的属性
}

设置apk输出名称

方式1:设置archivesBaseName

defaultConfig {
    project.ext.set("archivesBaseName", "myAPP-" + versionName + "-" + versionCode);
}

方式2:获取输出文件名直接替换

defaultConfig {
    applicationVariants.all {
    variant -> changeApkName(variant)
}

def changeApkName(variant) {
    def apk = variant.outputs[0].outputFile
    def newName = ""
    newName = apk.name.replace(project.name, project.name + "-" + android.defaultConfig.versionName + "-" + android.defaultConfig.versionCode)
    if (variant.buildType.name == "release") {
        newName = newName.replace("-" + variant.buildType.name, "")
    }
    variant.outputs[0].outputFile = new File(apk.parentFile, newName)
    if (variant.outputs[0].zipAlign) {
        variant.outputs[0].zipAlign.outputFile = new File(apk.parentFile, newName.replace("-unaligned", ""))
    }
}

签名配置

android {
    signingConfigs {
        release
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
}

File signFile = file(System.getenv('HOME') + "/.android/sign.properties")
if( signFile.canRead() ) {
    Properties p = new Properties()
    p.load(new FileInputStream(signFile))

    if( p!=null
    && p.containsKey('key.store')
    && p.containsKey('key.store.password')
    && p.containsKey('key.alias')
    && p.containsKey('key.alias.password')
    ) {
        println "RELEASE_BUILD: Signing..."

        android.signingConfigs.release.storeFile = file( p['key.store'] )
        android.signingConfigs.release.storePassword = p['key.store.password']
        android.signingConfigs.release.keyAlias = p['key.alias']
        android.signingConfigs.release.keyPassword = p['key.alias.password']

    } else {
        println "RELEASE_BUILD: Required properties in signing.properties are missing"
        android.buildTypes.release.signingConfig = null
    }
    } else {
        println "RELEASE_BUILD: signing.properties not found"
        android.buildTypes.release.signingConfig = null
}

ndk-build

自动生成mk

defaultConfig {
    sourceSets {
        main {
            jni.srcDirs = []
        }
    }

    ndk {
        moduleName "singalsdk"
        abiFilter "armeabi-v7a,x86,armeabi"
        stl "stlport_shared"
    }
}

使用定制mk

task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
    def androidMKfile = "$projectDir/jni/Android.mk"
    def applicationMKfile = "$projectDir/jni/Application.mk"
    def ndkDir = System.env.ANDROID_NDK_HOME
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        def ndkbuildcmd = $ndkDir/ndk-build.cmd
    } else {
        def ndkbuildcmd = $ndkDir/ndk-build
    }
    def execmd = ["$ndkbuildcmd","-j16","NDK_PROJECT_PATH=$buildDir",
    "APP_BUILD_SCRIPT=$androidMKfile", "NDK_APPLICATION_MK=$applicationMKfile"]
    println(execmd)
    commandLine execmd
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

利用productFlavor实现渠道包

初始化渠道包列表./../markets.list
productFlavors {
    def path="./../markets.list"
    file(path).eachLine { line->
        def channel = line
        if (!channel.trim().equals("")) {
            "$channel" {
                manifestPlaceholders=[channelname: channel]
            }
        }
    }
}

发布产物到Maven仓库(upload/publish)

Publishing artifacts(old)

Maven Publishing (new)

apply plugin: 'maven-publish'
apply plugin: 'signing'

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
    : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
    return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
    : "https://oss.sonatype.org/content/repositories/snapshots/"
}

def getRepositoryUsername() {
    return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}

def getRepositoryPassword() {
    return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}

group = GROUP 

task androidJavadocs(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    exclude '**/*.so'
}

task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
    classifier = 'javadoc'
    from androidJavadocs.destinationDir
}

task androidSourcesJar(type: Jar) {
    classifier = 'sources'
    from android.sourceSets.main.java.sourceFiles
}

task androidNativeJar(type: Jar) {
    classifier = 'so'
    from(new File(buildDir, 'libs'))
    include("**/*.so")
}

task androidNativeZip(type: Zip) {
    classifier = 'so'
    from(new File(buildDir, 'libs'))
    include("**/*.so")
}


android.libraryVariants

publishing {
    publications {
        maven(MavenPublication) {
            artifact bundleRelease
            artifact androidJavadocsJar
        }
    }
}

publishing {
    repositories {
        maven {
            credentials {
                username = getRepositoryUsername()
                password = getRepositoryPassword()
            }

            if(isReleaseBuild()) {
                url getReleaseRepositoryUrl()
            } else {
                url getSnapshotRepositoryUrl()
            }
        }
    }
}

生成jar文件

task clearJar(type: Delete) {
    delete 'build/libs/' + POM_ARTIFACT_ID + '_' + VERSION_NAME + '.jar'
}

task makeJar(type: Copy) {
    from('build/intermediates/bundles/release/')
    into('release/')
    include('classes.jar')
    rename ('classes.jar', POM_ARTIFACT_ID + '_' + VERSION_NAME + '.jar')
}

makeJar.dependsOn(clearJar, build)

收集apk到target目录

task collectApks(type:Copy) {
description = "Copies APKs and Proguard mappings to the target directory"
from 'build/outputs/apk'
exclude '**/*-unaligned.apk'
into 'target'
}
assembleRelease.finalizedBy collectApks

常用命令

gradle --help
gradle tasks //列出task列表
gradle asD (gradle assembleDebug) //编译debug打包
gradle asR (gradle assembleRelease) //编译release打包
gradle asD --refresh-dependencies //强制刷新依赖
gradle asD --parallel //并行编译
gradle asD --parallel-threads 3
gradle clean

参考资料

Monday, May 6, 2013

Hudson使用指导--了解进阶篇

一、 hudson了解进阶篇

hudson是什么?

hudson是一款持续集成工具.它具备以下功能点:
1. 易于安装部署
2. 友好的脚本配置界面
3. 支持分布式构建
4. 远程监控外部定时任务
5. 插件方便管理
6. 支持用户管理
7. 支持构建队列控制
8. 集成RSS/E-mail/IM-通过RSS发布构建结果或当构建失败时通过e-mail实时通知。
9. 生成JUnit/TestNG测试报告

如何部署安装?

首先,部署服务器需要jdk环境支持,其次可以通过以下有两种方式部署:
1. 运行命令行:java -jar hudson.war
2. 通过tomcat部署:进入Tomcat Manager,找到war file to deploy部署hudson.war
部署好后访问形如http://192.168.1.1/hudson ,web平台如下:

Tuesday, January 3, 2012

win7登陆黑屏问题

现象:

登陆后黑屏 ctrl+alt+del 有用,启动任务管理器没用,安全模式正常,explorer不知出了什么毛病?

分析:

1. 在安全模式下,关掉启动项,问题仍旧

2. 在安全模式下,查毒(没网上说 tlntsvi.exe ),问题仍旧

3. 在安全模式下,重装显卡驱动,问题仍旧(估计没有卸载干净)

4. 在安全模式下,卸载可疑软件,问题仍旧

5. 在安全模式下,创建新账号尝试,问题仍旧

6. 看到一篇资料,地址http://support.microsoft.com/kb/929135。执行干净启动来查找问题,看上去挺靠谱的。

1) 首先用了诊断启动,可以正常登陆。进去后有选择的启动,排查服务,

2) 结果发现后面有50项服务同时启用,问题就仍旧存在。估计里面含有显卡驱动(这是后面猜测的),这又让我重新回到分析显卡驱动。

7. 继续折腾,进安全模式下卸载显卡驱动,这回先不安装,可以正常登陆。装上去就不正常了。

8. 把硬件管理员叫来,换了个显卡,问题仍旧。

就这样分析了一天,尽是找不到原因,实在是让人崩溃。原本排斥没找到原因就重装系统的心开始动摇了,突然又很不死心的跑到机器面前,打开“控制面板”->“程序和功能”,就想着看谁不顺眼就卸谁:

因为近期有升级YY,内测版,可能不稳定吧,先卸了吧;

还有dxsdk_apr2006,这个已经装两三个星期了,已经没用了,也卸了吧;

QQ电脑管家,好像之前也被我卸载了;

结果,电脑鬼始神差的好起来了。

结论:

不装显卡驱动有 SDK(2006)正常,有显卡驱动没SDK(2006)正常,有显卡驱动有SDK(2006)就不正常了。

处理:

卸载dxsdk_apr2006,就可以正常登陆。

后序:

早知道,要一个个的卸,一下子几个,很容易搞乱了谁跟谁有冲突。

为了搞清楚, 我就先装上YY,然后重启进入,em,很正常。

再次装了SDK(2006),哦,no,又进不去了。

好吧,只能继续去安全模式把它给卸了。

不解的是,SDK(2006)已装了几星期,为什么突然间发作呢?

这又让人作什么解释呢?

Tuesday, July 12, 2011

[转]Getting Control of Third Party Libraries

How are people reigning in 3rd party libraries? Selecting which pakcages are suitable for use, which licenses? How does your Software Process identify when someone uses un-approved software/licenses?

   1. Martin Hache (Senior Technical Java J2EE Consultant at HP)
      Terrific question, I'm surprised no one's responded in the 24 hours since it's been posted. I'll tell you what we did but I would not exactly call it a solution, also, I found the problem to be larger than what you described in your post.

      Before I relate my experience, I would suggest that you look at Maven2, I hear that it has a system to manage library dependencies; I've never used it but those who love it, really love it.

      The problem for us (a web development team of 15 or so individuals working on a few dozen web apps) was not only 3rd party libraries but also the 3rd party libraries that 3rd party libraries used (4th party?). E.g. When the Spring JAR uses some Apache Common's JARS. The versions of these libraries would clash with the versions our applications wanted to use. This was particularly apparent in our own reusable components which could be shared across several applications. These amounted to 3rd party libraries with 3rd party libraries of their own.

      Unfortunately, we never did crack this nut to my satisfaction, we settled for establishing a few guidelines. We added version numbers to JARs if they didn't have them (so spring.jar became spring-2.0.2.jar) this allowed us to ID the version of a library with a simple look. On top of that we basically leveraged our build order: components distributed the jars they needed to compile to the child apps/components that depended on them. Those dependents modules didn't usually contain the JARs if one of the components they depended on distributed it. If a child app/component needed a newer JAR than what the parent component was offering then we would create a new version of the parent with the new version of the JAR. Clashes were handled manually, by talking through them.

      Your question may have more to do with licensing and authority to use a library, but we didn't do much of that, again a manual vetting of the Jar and licensing is what we did.

   2. Curt Yanko (Sr IS Architect at UHG)
      I have left it *open-ended* since I'm fishing a bit here and don't want to influence the answers too much.
      I am indeed talking about the full monty as-it-were, and am interested in creating a Definitive Software LIbrary of *approved* components and then contraining the build system to just those. Additionaly, failing a build should I see a license that scares me, I'm looking at you Affero!
      Maven is indeed central to our strategy. Site reports and their BOM's play a key role in at least getting visibility. Now I want control.
     
   3. Ben Weatherall (Configuration Manager at PDX, Inc.)
      First, I want to point out a commercial solution from OpenLogic called OLEX. It does the license analysis (are these licenses compatible?) and license obligations (if you use this, in this fashion, you must do ...). It also has functionality to scan both source and binaries to determine which FOSS components are included, whether you intended for them to be or not. And no, I am not associated with OpenLogic - just paranoid enough to be checking them out.

      Now, as to what we actually (try to) do, whenever someone decides to add a third party component to the mix, they are required to submit links to the "owner" and to wherever they acquired the binaries. They are then allowed to commit to the primary repository only those binaries that are actually built from the component source. All of the other dependent components that may be supplied "for convenience" must be checked that they are available from an "owner" and then the process recurses.

      I enforce this, otherwise no license checks would ever be done and there would be no way I could "escrow" the source in case of legal challenge. Periodically, the architecture team, product managers and CM get together to review changes to our third party repository and how they are being used. We try to distribute the work since it is very time intensive to track everything back to the "owner" level and verify it.

      Curt, we do not use Maven for the very reason you like it - it will find what it needs even if I don't know about it. I am not totally happy with our solution since it is so manually intensive, but it is what I have today. It will evolve. Either that or I need to revoke Development's right to update third party components and allocate that function to an already overloaded team.

      We get our BOMs, etc. from a use of AccuRev, cvs and AnthillPro. The combination has kept me out of too much trouble so far.


--
Elian
 
Configuration Manage Engineer
MSN: smallfish961@hotmail.com
Email: smallfish382+work@gmail.com