[Git] 다른 브랜치와 합치지는 않되 특정 커밋은 가져오고 싶은 경우


여러 브랜치에서 작업을 하다가 공통된 코드에 변경이 있을 경우, 병합은 하지 않으면서 똑같은 커밋을 여러 브랜치에서 사용하고 싶을 때가 있습니다. 그럴 때에는 체리픽 (cherry-pick) 명령어를 사용하면 됩니다.


// 만약에 브랜치1에 있는 abcd1234라는 SHA-1 ID로 시작하는 커밋을 브랜치2에 적용시키려면


git checkout 브랜치2

git cherry-pick abcd1234


[토치 (Torch)] error: more than one operator "==" matches these operands

 

Lua 기반의 딥 러닝 프레임워크인 토치(Torch)를 빌드하다 보면 error: more than one operator "==" matches these operands 와 같은 에러 메시지가 뜰 때가 있습니다. 이 현상은 CUDA가 9.0 버전에서부터 절반 정확도의 부동 소수점 연산을 지원하면서 생기는 문제입니다. 이럴 때에는 빌드 전에 다음과 같이 환경 변수를 추가로 지정해주면 됩니다.

 

export TORCH_NVCC_FLAGS="-D__CUDA_NO_HALF_OPERATORS__"

 

이 글을 쓸 때에 https://github.com/torch/torch7/issues/1086 를 참조하였습니다.

[자바] 밑줄 (_) 이 들어가는 JNI 함수명


JNI에서는 함수명에 자바의 패키지 경로를 모두 쓰게 되는데, 그 때에 .(점)을 _(밑줄)로 치환하게 됩니다. 따라서 자바 함수명 자체에 밑줄이 있으면 문제가 생깁니다. 이런 경우 자바 함수명에 있는 밑줄은 JNI에서 _1로 치환하면 됩니다. 아래는 간단한 예제입니다.


// 자바

package com.tistory.crmn;

public class Hello {

    static native int get_hello();

}



// JNI

extern "C" JNIEXPORT jint JNICALL

Java_com_tistory_crmn_Hello_get_1hello(JNIEnv* env, jobject thiz) { // get_1hello에 주목하세요

    return (jint) 1;

}


[안드로이드] CMakeLists.txt 파일 설명


안드로이드에서 JNI를 통해 C나 C++ 코드를 사용하려면 CMake나 ndk-build중 하나를 사용해야 합니다. 이 글에서는 CMakeList.txt에 사용되는 여러 옵션에 대해 알아보겠습니다.


1. 사용할 CMake의 최소 버전 설정


cmake_minimum_required(VERSION 3.4.1)



2. 안드로이드에서 사용할 라이브러리의 이름과 공유 및 정적 여부, 소스 코드 경로 설정


아래 예제의 경우 라이브러리의 이름은 native-lib이고 공유 라이브러리이며 소스 코드 경로는 src/main/cpp/native-lib.cpp 입니다. 참고로 이렇게 컴파일을 하면 CMake는 컴파일 결과물을 libnative-lib.so 라는 이름으로 저장합니다.


add_library( native-lib

             SHARED

             src/main/cpp/native-lib.cpp )



3. 소스 코드에서 사용하는 헤더 파일이 들어있는 디렉토리 설정


설정해주지 않아도 동기화 이후에는 자동으로 헤더 파일이 인식되기는 합니다만, 설정해주면 컴파일 단계에서부터 연결된 헤더 파일을 볼 수 있습니다.


include_directories(src/main/cpp/include/)



4. 이미 존재하는 안드로이드 NDK 기본 라이브러리 사용하기


find_library()와 target_link_libraries()를 사용하면 안드로이드 NDK에서 기본으로 제공하는 라이브러리를 따로 컴파일할 필요 없이 바로 사용할 수 있습니다. 아래 예제는 NDK에 있는 log라는 라이브러리를 찾아서 log-lib이라는 변수명으로 저장한 뒤에 native-lib에서 불러와서 사용하는 코드입니다. log-lib이 변수명이기 때문에 target_link_libraries() 에서는 ${log-lib} 으로 표기됩니다.


find_library( log-lib

              log )

target_link_libraries( native-lib

                       ${log-lib} )



5. 소스 코드 형태로 존재하는 안드로이드 NDK 기본 라이브러리 사용하기


4번 경우와 유사한데 이 경우는 안드로이드 NDK 기본 라이브러리가 컴파일되지는 않고 소스 코드 형태로 존재한다는 점이 다릅니다. 사용법은 3번과 4번을 합친 형태입니다.


add_library( app-glue

             STATIC

             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )


target_link_libraries( native-lib

                       app-glue

                       ${log-lib} )



6. 이미 컴파일 된 외부 라이브러리를 불러와서 사용하기 (매우 중요)


현업에서 안드로이드 개발을 하다 보면 다른 사람이 만든 라이브러리를 이미 컴파일 된 상태로 불러와서 사용해야 할 경우가 정말 많습니다. 이 경우는 add_library()와 set_target_properties()를 사용해야 합니다. add_library()에서는 이 라이브러리가 이미 컴파일 된 상태라는 것을 알려주기 위해 IMPORTED를 사용하고, set_target_properties()에서는 컴파일 된 파일의 경로를 지정해줍니다. 여러가지 CPU 구조를 지원하려면 ANDROID_ABI 변수를 사용하면 됩니다. 컴파일 단계에서 헤더 파일 정보를 보려면 include_directories()를 사용하면 되고, 외부 라이브러리를 불러온 뒤에는 target_link_libraries()를 사용해서 원하는 라이브러리에 연동시키면 됩니다.


아래는 libimported-lib.so 파일을 불러와서 imported-lib 이라는 변수에 저장한 뒤에 native-lib에서 imported-lib을 다른 라이브러리와 함께 사용하는 예제입니다. PROPERTIES IMPORTED_LOCATION는 IMPORTED_LOCATION이라는 값을 정해주겠다는 이야기입니다.


add_library( imported-lib

             SHARED

             IMPORTED )


set_target_properties( imported-lib

                       PROPERTIES IMPORTED_LOCATION

                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )


include_directories( imported-lib/include/ )


target_link_libraries( native-lib imported-lib app-glue ${log-lib} )



이 정도면 안드로이드에서 일반적으로 CMake를 사용하는 데에는 큰 문제가 없을 것입니다.

[VI, VIM] 정규식에서 non-greedy 하게 검색하기 (욕심부리지 않기)


VI의 정규식이 펄이나 파이썬 등의 정규식과 크게 다른 점 중 하나는 non-greedy (욕심부리지 않기) 연산자입니다. 대부분의 경우 물음표 기호가 사용되는데 VI에서는 \{-}가 사용됩니다. 예를 들면 다음과 같습니다.


:%s/hello.\{-}://g


라고 하면 hello에서 가장 가까이 있는 : 까지만 사라지게 됩니다. 펄이나 파이썬이었으면 .? 이런 식으로 사용했을 거라, 지레짐작으로 VI에서 열심히 \? 를 시도해보다가 시행착오를 엄청 했습니다.

[안드로이드] Error:Could not find method jackOptions() for arguments


그래들 파일에서 아래 블록 부분을 지워준 뒤 안드로이드 스튜디오를 껐다가 다시 실행하면 문제가 해결됩니다. 


// 이 부분을 삭제하시면 됩니다.

jackOptions {

    enabled true

}


[안드로이드] No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android


안드로이드에서 사용되는 NDK 버전이 올라가면서 MIPS형 CPU에 대한 지원이 중단되었습니다. 그런데 build.gradle에 지정되어있는 gradle 버전이 낮으면 안드로이드 스튜디오가 MIPS에 대한 정보를 계속 찾으려고 하다가 위와 같은 에러를 내게 됩니다. 이럴 때에는 gradle 버전을 3.1.4 나 그 이상으로 설정해준 뒤 안드로이드 스튜디오를 껐다가 다시 실행하면 문제가 해결됩니다.


dependencies {

    classpath 'com.android.tools.build:gradle:3.1.4'

}



[파이썬] 아나콘다 업데이트하기


아나콘다를 사용하다 보면 아나콘다 자체 및 부속 라이브러리들을 업데이트 해야 할 일이 생기곤 합니다. 그럴 때에는 다음과 같이 하면 쉽게 전체 업데이트를 할 수 있습니다.


conda update -n root conda

conda update --all

conda update --all


conda update -n root conda 는 conda 자체를 최신 버전으로 업데이트하는 명령입니다.

conda update --all 이 본격적으로 업데이트를 하는 명령인데, 경우에 따라 두 번 실행해야 다 업데이트가 되는 경우가 있었습니다.


( 다음 링크를 참고했습니다. https://stackoverflow.com/questions/45197777/how-do-i-update-anaconda#45197778 )

윈도폰 8에서 gmail을 사용해서 이메일을 보낼 때 이메일이 중복되는 경우가 있습니다. 원인과 해결책은 다음과 같습니다.


윈도폰에서는 '보낸 편지함'이라고 나타나고 gmail에서는 'Sent Items'이라고 나타나는 폴더가 있습니다. 이 폴더는 윈도폰이 직접 만드는 폴더입니다. gmail 자체 폴더는 '보낸편지함'입니다. 띄어쓰기가 없습니다.


윈도폰에서 '보낸 편지함' 동기화를 중지하시면 더이상 gmail을 사용해서 이메일을 보낼 때 중복되지 않습니다.


[JUnit] 명령줄(커맨드 라인)에서 JUnit 실행하기


명령줄(커맨드 라인)에서 JUnit을 실행하시려면 다음과 같이 하시면 됩니다. 리눅스와 윈도에서의 명령어가 조금 다른데, 리눅스에서는 :을 쓰고 윈도에서는 ;을 씁니다. 한편 JUnit 버전(4.x와 3.x)에 따라서도 명령어가 조금 달라집니다.


실행하실 때 test class name은 현재 디렉토리 혹은 path에 지정된 디렉토리에 있어야 합니다.


< JUnit 4.x >


리눅스

java -cp .:/path/to/junit_4.x/junit.jar org.junit.runner.JUnitCore [test class name]


윈도

java -cp .;/path/to/junit_4.x/junit.jar org.junit.runner.JUnitCore [test class name]


< JUnit 3.x >


리눅스

java -cp .:/path/to/junit_3.x/junit.jar junit.textui.TestRunner [test class name]


윈도

java -cp .;/path/to/junit_3.x/junit.jar junit.textui.TestRunner [test class name]


+ Recent posts