Categories
discuss

cmake – targeting multiple architectures at once without manual cleaning between builds

I am developing a cross-platform C++ library for Android and iOS and I am using cmake to prepare build scripts.

A project structure looks something like:

somelib
|
├─ .gitignore
|
├── src
│   └── CMakeLists.txt
│   └── Doxyfile.in
|   └── include (Public headers)
│       └── somelib
│           └── somelib.hpp
│   └── somelib
│       └── CMakeLists.txt
│       └── somelib.cpp
│       └── ....hpp, ....cpp
│       └── test
│           └── test_classname.cpp
│   └── libs (source of 3rd party libs)
│       └── 3rd_party_lib_1
│           └── CMakeLists.txt
│           └── ...
│       └── ...
│           └── CMakeLists.txt
│           └── ...
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
├── toolchains
│   └── andoid
│       └── android.toolchain.cmake
│       └── ...
│   └── ios
│       └── ios.toolchain.cmake
│       └── ...
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── build
│   └── build.sh
│   └── Doxyfile
│   └── ...
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
├── dist (distribute)
│   └── docs
│       └── index.html
│       └── ...
|   └── include (Public headers)
│       └── somelib.hpp
│   └── local
|       └── somelibtest (executable tests)
│   └── android
│       └── Debug
│           └── armeabi
│           └── armeabi-v7a
│           └── ...
│       └── Release
│           └── armeabi
│           └── armeabi-v7a
│           └── ...
│   └── ios
│       └── Debug
│           └── armv
│           └── armv7
│           └── ...
│       └── Release
│           └── armv
│           └── armv7
│           └── ...
|

I am running cmake from ./build/ path by executing build.sh which in case of building for android, looks something like this:

build.sh:

...

TARGETS="armeabi-v7a armeabi x86 mips arm64-v8a mips64"

mkdir -p "$BUILD_PATH"

for TARGET in $TARGETS
do

    cmake -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_TOOLCHAIN} -DANDROID_NDK=${ANDROID_NDK} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DANDROID_ABI=${TARGET} -DPROJ_HOME=${PROJ_HOME} ../src

    make -j32

  done

fi
...

If I am building for one particular architecture, for example setting TARGETS to “arm64-v8a” only, the library builts well. In case if I want to build a library for multiple architectures at once then it does not work well since cmake prepares build script specifically for each platform/architecture. I get linker errors such as “incompatible target” durring the build.

What is the best practice to build libraries targeting multiple platforms and multi-architecture?

How can I avoid cleaning build script files before preparing to build for another architecture?

Thank you for any suggestions!


PS: Here are some lines from main src/CmakeLists.txt file:

cmake_minimum_required(VERSION 3.6.0 FATAL_ERROR)

include(GNUInstallDirs)

# Set default build type
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

## Output directories

if (IOS)
  set(REL_OUTPUT_DIR "ios/${CMAKE_BUILD_TYPE}/${IOS_ARCH}")
elseif (ANDROID)
  set(REL_OUTPUT_DIR "android/${CMAKE_BUILD_TYPE}/${ANDROID_ABI}")
else()
  set(REL_OUTPUT_DIR "local")
endif()
set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/../dist/${REL_OUTPUT_DIR})
set(DESTDIR ${CMAKE_BINARY_DIR}/../dist/${REL_OUTPUT_DIR})

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${OUTPUT_DIR}") # Static libraries
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_DIR}") # Dynamic libraries
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") # Executables

# Include libraries
add_subdirectory(libs/3rd_party_lib_1)
add_subdirectory(libs/3rd_party_lib_n)

Answer

An option, as I eluded to in the comments, is to use one build directory per target architecture

...

TARGETS="armeabi-v7a armeabi x86 mips arm64-v8a mips64"

for TARGET in ${TARGETS}
do    
    # create one build dir per target architecture
    mkdir -p ${BUILD_PATH}/${TARGET}
    cd ${BUILD_PATH}/${TARGET}

    cmake -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} -DCMAKE_TOOLCHAIN_FILE=${ANDROID_TOOLCHAIN} -DANDROID_NDK=${ANDROID_NDK} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DANDROID_ABI=${TARGET} -DPROJ_HOME=${PROJ_HOME} ../../src

    make -j32

    cd -    
done

...

This will result in a tree looking somewhat like the following

project/
+--- src/
+--- build/
     +--- armeabi-v7a/
     +--- armeabi/
     +--- x86/
     +--- mips/
     +--- arm64-v8a/
     +--- mips64/
Categories
discuss

Spring Data JPA How to use Kotlin nulls instead of Optional

I’m writing a Spring Boot app with Spring Data JPA and Kotlin, and I’ve noticed that in CrudRepository there is the following method:

Optional<T> findById(ID id);

I’m using Kotlin, though, which has much more fluent ways of dealing with nulls than Optional. Does anyone know how I would convert that method to work like this?

fun findById(id: ID): T?

When I extend Repository itself and create a repo with that signature I get the error:

java.lang.ClassCastException: java.util.Optional cannot be cast to com.books.Book

Answer

As of Spring Data Lovelace SR4 / Spring Boot 2.1.2, a CrudRepository.findByIdOrNull(id: ID): T? = findById(id).orElse(null) Kotlin extension now provides out of the box a way to retrieve nullable entities in Spring Data.

If for performance reasons you would like to avoid the usage of Optional<T> wrapper, be aware that you have also the possibility to create a custom interface with a findFooById(id: ID): T? function. Query execution is store specific, but and most are using internally nullable values and will avoid the cost of Optional<T> wrapper. Notice this overhead should be negligible for most use cases, so using the builtin extension is recommended method.

See DATACMNS-1346 for more details.

Categories
discuss

Rxjs: Merge two streams with one stream that depends of another

I have a stream that calls a service that returns a stream that needs the info of the original stream for the request.

this.messages$ = this.selectedChat$
.switchMap(chat => this.chatService.subscribeMessages(chat.room))
.map(messages) =>
  messages.map((message: any) => {
    //Here need add information of the chat object
    return message;
  })
);

All operators that I see that can merge the streams and separate them later (like combineLatest) receive parameters, therefore, I can´t use the original stream info to call the service that generates the other stream, and I would not like to use subscribe on the original stream and return a new stream inside the subscribe because it’s a little messy code.

Any advice?

Answer

Use the selector function in the switchMap operation:

this.messages$ = this.selectedChat$
.switchMap(chat => this.chatService.subscribeMessages(chat.room), 
(chat,messages)=>({chat,messages})) // create a new object, using the inner observable and the mapped one
.map(data =>
  data.messages.map((message: any) => {
    // Here data.chat has the chat information
    return message;
  })
);

For more information about the switchMap operator check here

Categories
discuss

Firebase Database not committing online data blocking Listeners

I am using the Firebase Database service to synchronize users data. I enabled the offline compatibilities and the problem is that after some months the of usage, the users data is not committed into the online database apparently because the users phone systems are blocking the application internet connection.

In some cases, i managed to guide the users enable the “unlimited data usage” option, but isn’t working for everyone.

In my case, the problem is that the listener:

void onDataChange(DataSnapshot var1);

from ValueEventListener, is not fired when a huge amount of data is stored offline and not committed, and is blocking all the behaviors.

I don’t have online storage limitation because I have the Blaze plan ( pay for consuming ).

The transactions are not committed too, and fires “The transaction was overridden by a subsequent set” with the error code -9.

The Connection detector provided by Firebase is always printing “not connected “

I also tried to alternate goOffline() with goOnline() but nothing happens.

I don’t understand why the phone could block my app from synchronizing and let apps like Facebook and Youtube to consume a large amount of internet data.

This behavior is only happening on the Android devices, there is no problem on iOS phones that are using the same Firebase Database.

Doesn’t work either with 4g, WI-FI nor with VPN ( used Opera VPN ).

Update 1:

The logs contains at launch for ~10 times:

11-13 21:12:28.477 15765 15856 D PersistentConnection: pc_0 - Scheduling connection attempt
11-13 21:12:28.477 15765 15856 D ConnectionRetryHelper: Scheduling retry in 26091ms
11-13 21:12:54.597 15765 15856 D PersistentConnection: pc_0 - Trying to fetch auth token
11-13 21:12:55.747 15765 15856 D PersistentConnection: pc_0 - Error fetching token: An internal error has occurred. [ 
TOKEN_EXPIRED ]

When I’m trying to insert new data:

RepoOperation: Aborting transactions for path: [the path]

Answer

After a long investigation, I found out that the token was not refreshing automatically.

First of all, check if the current user is logged in with FirebaseAuth.AuthStateListener

To check if I need to refresh the token

1) Check if the application has internet connection:

    public static boolean isOnline(Context context)
    {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        return networkInfo != null && networkInfo.isConnectedOrConnecting();
    }

2) Then I check if the database is connected to: Detecting Connection State

If the app has an internet connection and the database is not connected then I try to refresh the token:

try
{
    user.getIdToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>()
    {
        @Override
        public void onComplete(@NonNull Task<GetTokenResult> task)
        {
            if (task.isSuccessful())
            {
                //succcess
            } else
            {
                //need login again
            }
        }
    });
}catch(Exception e)
{
    //need login again
}

If there is an exception or the completion task fails then I try to login again the user. In most of the cases will be a transparent login, so will not be displayed to the user, because will use the credentials already stored by the sdk itself.

I think this is a hack because affects only a few users so it’s an sdk bug.

Categories
discuss

Android Studio 3.0 and app freezing

I’ve updated my android studio from 2.x to android 3.0 stable.

Since then when I try to push an application to my Nexus 7 2012 with cyanogenmod 12.1 (android 5.1.1) the entire system freeze and crash.

At the reboot the system show the launcher but it’s all friezed until I uninstall the app. I’ve tried with different apps, also release compiled, and different Nexus 7 (same hardware and software), exactly same results.

With different devices I have no problems. What’s going on? Thank you.

11-06 13:56:05.681 2304-2304/? E/memtrack: Couldn't load memtrack module (No such file or directory)
11-06 13:56:05.681 2304-2304/? E/android.os.Debug: failed to load memtrack module: -2
11-06 13:56:05.737 2304-2304/? D/AndroidRuntime: Calling main entry com.android.commands.pm.Pm
11-06 13:56:06.057 489-525/system_process I/ActivityManager: Start proc 2317:com.android.defcontainer/u0a6 for service com.android.defcontainer/.DefaultContainerService
11-06 13:56:06.080 2317-2327/? I/art: Debugger is no longer active
11-06 13:56:06.132 489-525/system_process D/PackageManager: /data/app/vmdl835727952.tmp already staged; skipping copy
11-06 13:56:06.416 489-525/system_process D/PackageManager: Renaming /data/app/vmdl835727952.tmp to /data/app/com.unipiazza.fismunipiazza-1
11-06 13:56:06.463 489-525/system_process I/PackageManager: Running dexopt on: /data/app/com.unipiazza.fismunipiazza-1/base.apk pkg=com.unipiazza.fismunipiazza isa=arm vmSafeMode=false
11-06 13:56:06.487 2345-2345/? I/dex2oat: /system/bin/dex2oat --zip-fd=6 --zip-location=/data/app/com.unipiazza.fismunipiazza-1/base.apk --oat-fd=7 --oat-location=/data/dalvik-cache/arm/data@app@com.unipiazza.fismunipiazza-1@base.apk@classes.dex --instruction-set=arm --instruction-set-features=default --runtime-arg -Xms64m --runtime-arg -Xmx512m --swap-fd=8
11-06 13:56:06.525 489-504/system_process I/art: Background partial concurrent mark sweep GC freed 101584(5MB) AllocSpace objects, 57(1225KB) LOS objects, 33% free, 12MB/19MB, paused 2.001ms total 105.069ms
11-06 13:56:06.538 2345-2345/? I/dex2oat: Decided to run without swap.
11-06 13:56:06.629 2345-2345/? I/dex2oat: dex2oat took 141.194ms (threads: 4) arena alloc=104KB java alloc=48KB native alloc=1371KB free=28KB
11-06 13:56:06.737 489-525/system_process V/BackupManagerService: restoreAtInstall pkg=com.unipiazza.fismunipiazza token=1 restoreSet=0
11-06 13:56:06.737 489-525/system_process V/BackupManagerService: Finishing install immediately
11-06 13:56:06.741 489-525/system_process W/Settings: Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.

                                                      --------- beginning of crash
11-06 13:56:06.749 1061-1127/com.cyanogenmod.trebuchet A/libc: invalid address or address of corrupt block 0xaee9 passed to dlfree
11-06 13:56:06.750 1061-1127/com.cyanogenmod.trebuchet A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 1127 (launcher-loader)
11-06 13:56:06.750 138-138/? I/DEBUG: property debug.db.uid not set; NOT waiting for gdb.
11-06 13:56:06.750 138-138/? I/DEBUG: HINT: adb shell setprop debug.db.uid 100000
11-06 13:56:06.750 138-138/? I/DEBUG: HINT: adb forward tcp:5039 tcp:5039
11-06 13:56:06.752 489-573/system_process I/InputReader: Reconfiguring input devices.  changes=0x00000020
11-06 13:56:06.756 489-489/system_process D/BackupManagerService: Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.unipiazza.fismunipiazza flg=0x4000010 (has extras) }
11-06 13:56:06.768 489-489/system_process W/BackupManagerService: Removing schedule queue dupe of com.unipiazza.fismunipiazza
11-06 13:56:06.790 489-511/system_process W/Searchables: No global search activity found
11-06 13:56:06.810 138-138/? I/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-06 13:56:06.810 138-138/? I/DEBUG: Build fingerprint: 'google/nakasi/grouper:5.1/LMY47D/1743759:user/release-keys'
11-06 13:56:06.810 138-138/? I/DEBUG: Revision: '0'
11-06 13:56:06.810 138-138/? I/DEBUG: ABI: 'arm'
11-06 13:56:06.810 489-651/system_process I/ActivityManager: Start proc 2351:org.cyanogenmod.themes.provider/u0a15 for broadcast org.cyanogenmod.themes.provider/.AppReceiver
11-06 13:56:06.811 138-138/? I/DEBUG: pid: 1061, tid: 1127, name: launcher-loader  >>> com.cyanogenmod.trebuchet <<<
11-06 13:56:06.812 138-138/? I/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdeadbaad
11-06 13:56:06.798 138-138/? W/debuggerd: type=1400 audit(0.0:218): avc: denied { write } for name="ndebugsocket" dev=mmcblk0p9 ino=1730173 scontext=u:r:debuggerd:s0 tcontext=u:object_r:system_ndebug_socket:s0 tclass=fifo_file
11-06 13:56:06.832 657-657/com.android.nfc A/libc: invalid address or address of corrupt block 0x8d09 passed to dlfree
11-06 13:56:06.832 657-657/com.android.nfc A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 657 (com.android.nfc)
11-06 13:56:06.858 138-138/? I/DEBUG: Abort message: 'invalid address or address of corrupt block 0xaee9 passed to dlfree'
11-06 13:56:06.858 138-138/? I/DEBUG:     r0 00000000  r1 401fbdec  r2 deadbaad  r3 00000000
11-06 13:56:06.858 138-138/? I/DEBUG:     r4 0000aee9  r5 401fd0d8  r6 4000a000  r7 0000aef1
11-06 13:56:06.859 138-138/? I/DEBUG:     r8 6c1ee42c  r9 6c1ee4ec  sl 40222236  fp 4022223f
11-06 13:56:06.859 138-138/? I/DEBUG:     ip 00000000  sp 6c1ee3d8  lr 401cd20b  pc 401cd20c  cpsr 600e0030
11-06 13:56:06.859 138-138/? I/DEBUG: backtrace:
11-06 13:56:06.859 138-138/? I/DEBUG:     #00 pc 0002920c  /system/lib/libc.so (dlfree+1239)
11-06 13:56:06.859 138-138/? I/DEBUG:     #01 pc 0000f363  /system/lib/libc.so (free+10)
11-06 13:56:06.859 138-138/? I/DEBUG:     #02 pc 00012b07  /system/lib/libandroidfw.so (android::ResStringPool::uninit()+38)
11-06 13:56:06.859 138-138/? I/DEBUG:     #03 pc 00013843  /system/lib/libandroidfw.so (android::ResXMLTree::uninit()+12)
11-06 13:56:06.859 138-138/? I/DEBUG:     #04 pc 00013861  /system/lib/libandroidfw.so (android::ResXMLTree::~ResXMLTree()+4)
11-06 13:56:06.859 138-138/? I/DEBUG:     #05 pc 00010527  /system/lib/libandroidfw.so (android::AssetManager::getPkgName(char const*)+258)
11-06 13:56:06.859 138-138/? I/DEBUG:     #06 pc 00010589  /system/lib/libandroidfw.so (android::AssetManager::getBasePackageName(unsigned int)+68)
11-06 13:56:06.859 138-138/? I/DEBUG:     #07 pc 00082007  /system/lib/libandroid_runtime.so
11-06 13:56:06.859 138-138/? I/DEBUG:     #08 pc 0027b473  /data/dalvik-cache/arm/system@framework@boot.oat
11-06 13:56:06.873 2351-2351/? A/libc: invalid address or address of corrupt block 0x451 passed to dlfree
11-06 13:56:06.874 2351-2351/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 2351 (themes.provider)
11-06 13:56:06.891 489-525/system_process I/art: Explicit concurrent mark sweep GC freed 16254(1113KB) AllocSpace objects, 5(80KB) LOS objects, 33% free, 12MB/18MB, paused 1.753ms total 147.497ms
11-06 13:56:06.896 2304-2304/? I/art: System.exit called, status: 0
11-06 13:56:06.896 2304-2304/? I/AndroidRuntime: VM exiting with result code 0.
11-06 13:56:07.256 2375-2375/? D/AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
11-06 13:56:07.260 2375-2375/? D/AndroidRuntime: CheckJNI is OFF

Answer

had the same issue after updating to version 3.

solved this by installing Android SDK Buildtools version 27.0.1 and change the buildToolsVersion to ‘27.0.1’ in my build.gradle

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..