I would like to use cURL library in my android application in native code (using NDK r5b, the latest). After researching online, it seems the only way to use cURL in android is to build the entire android source tree with curl in it, and somehow this generates a necessary config file for cURL to work on Android. I don't have any experience building the android sources from scratch and was wondering if there is a way to use cURL library in Android without having to rebuild android from source. Ideally, being able to just use cURL as a static or shared library would be perfect. I tried following the steps mentioned here...
http://curl.haxx.se/mail/lib-2009-12/0071.html
but end up getting errors in the file curlrules.h like CURL_SIZEOF_LONG definition is missing!
I assume these errors are due to not having that config file I mentioned but the steps in the above link didn't mention any of that and reported success. Any ideas?
I'm on a similar quest! I'm working on an app right now that requires cURL and just tonight in my search I came across your post here, and what I believe to be the answer:
http://thesoftwarerogue.blogspot.com/2010/05/porting-of-libcurl-to-android-os-using.html
Unlike the link you referenced, there are several follow-up comments from other people who claim to have success also following the instructions. If you manage to get it compiled before me, and wouldn't mind sending me the library, post a follow up here! (I'm pretty new to stack overflow so I don't know if you can pm.) Hope this works out for both of us!
It seems that there are projects on github that automated both openssl and libcurl for NDK build:
https://github.com/jahrome/curl-android
https://github.com/guardianproject/openssl-android
Going to use those in my own app, so I can have single library to deal with backend communication for both iOS and Android...
After check all possibles post about this, I finally got a good compilation using a Linux x64 machine and Curl version 7.37.0 at path ${android-ndk-r10}.
Maybe this steps can help you:
1º
${android-ndk-r10}/build/tools/make-standalone-toolchain.sh --platform=android-15 --arch=armv7-a --toolchain=arm-linux-androideabi-4.8 --install-dir=./tmp/android-15
2º
export CC="${android-ndk-r10}/external/curl/tmp/android-15/bin/arm-linux-androideabi-gcc"
3º
./configure --host=arm-linux --enable-cross-compile --enable-threaded-resolver --disable-shared --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-manual --enable-proxy --enable-ipv6 --enable-cookies --enable-symbol-hiding --disable-versioned-symbols --disable-soname-bump --disable-sspi --disable-ntlm-wb --prefix=${android-ndk-r10}/external/curl/build/curl-7.37.0
4º
make -j4
5º
make install
You will get a build version at ${android-ndk-r10}/external/curl/build/curl-7.37.0.
If you are using a 64bits machine to compile, maybe 2 defines are bad, and you get this error:
error: size of array '__curl_rule_01__' is negative
I solve redefining the variables in file ${CurlbuildAndroid}/include/curl/curlbuild.h (Its dangerous to do this, but it worked!):
CURL_SIZEOF_LONG 4
CURL_TYPEOF_CURL_OFF_T 4
I followid this link. And it works for me. I did not have to download the whole android repository in order to compile the libcurl
You can choose to download cURL for android at https://play.google.com/store/apps/details?id=io.github.faywong.curl
"CURL_SIZEOF_LONG definition is missing!"
there is a way for it .
change the curlbuild.h at line number 162
add like this,if you are arm32 platform.
//----------------------------------------------add
# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_FORMAT_OFF_T "%lld"
# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
//#define __SYMBIAN32__
I had a similar question which didn't get answered and thus was automatically removed :(
Anyway I've successfully used curl on android and have uploaded a compiled version to help the people still searching.
Download: libcurl_for_arm
I also required a typecheck-gcc.h file which I've amended and uploaded here too
Download: typecheck-gcc.h
Related
I think I've read every suggestion on the internet at this point to no avail, so I'm hoping I can get some help here.
Repro
git clone https://github.com/banool/aclip.git
cd aclip/frontend/native
cargo ndk -t armeabi-v7a -o ../android/app/src/main/jniLibs build
The code in question: https://github.com/banool/aclip.
Relevant env:
PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig/
LDFLAGS=-L/opt/homebrew/opt/openssl#1.1/lib
CPPFLAGS=-I/usr/local/opt/openssl#1.1/include
CFLAGS=-I/opt/homebrew/opt/openssl#1.1/include
ANDROID_NDK_HOME=/Users/dport/Library/Android/sdk/ndk
Output
Running the above gives me this: https://gist.github.com/d2564965bbd5e4d8bf72c3132c87255f.
Some thoughts on what's going on here:
I see it says NDK API level: 21. Is this level not the same as the NDK level, which as you can see in the previous line is 24?
I have tried setting PKG_CONFIG_SYSROOT_DIR to the NDK directory. That gives me instead this rather cryptic error: https://gist.github.com/b28eae5f666fccaffe80278a5a8a80e1. I wonder if there is a better directory to use.
I did everything here relevant to the second part, where I'm trying to use a newer NDK: http://cjycode.com/flutter_rust_bridge/template/setup_android.html.
I have set the libunwind stuff suggested here: http://cjycode.com/flutter_rust_bridge/template/setup_android.html. That helped with the gcc error in the second gist here, but I've still got the ssl and crypto errors.
Any tips on how to proceed would be very much appreciated.
Thanks!
For me I was able to skirt around the issue by doing this.
First, figure out what openssl crate version we're relying on:
$ cargo tree --target=x86_64-unknown-linux-musl -i openssl-sys | grep openssel
openssl-sys v0.9.74
└── openssl v0.10.40
Then add something like this to your Cargo.toml:
openssl = { version = "0.10.40", features = ["vendored"] }
This avoids the need for the system openssl.
Protobuf is a very widely used library, so I want to use it in Flutter's C++ code to serialize and deserialize my data. However, I find that compiling and linking the protobuf library is not a trivial task... I failed many times before finding out the correct solution, so I want to share it here using Q&A style.
Preparation
Firstly, of course, you need to generate your protobuf files. This is out the scope of this tutorial, so you can look at the official guide. Suppose you already have hello.pb.h and hello.pb.cc generated.
iOS
Add the following to your xxx.podspec, if you are developing a package/plugin that uses C++ code which needs protobuf. If it is your may code that needs protobuf, things are also similar.
Pod::Spec.new do |s|
...normal things...
s.pod_target_xcconfig = {
'HEADER_SEARCH_PATHS' => '$(SRCROOT)/Protobuf-C++/src',
}
s.dependency 'Protobuf-C++', '~> 3.18.0'
end
In addition, you need to add the following in your main project's Podfile. For example, if you are developing a package that is used by 10 projects, each of them needs to add the following section.
post_install do |installer|
...normal things...
installer.pods_project.targets.each do |target|
# print "target=", target, "\n"
if target.name == "Protobuf-C++"
target.build_configurations.each do |config|
config.build_settings['HEADER_SEARCH_PATHS'] = '$(SRCROOT)/Protobuf-C++/src'
end
end
end
end
Then clean and build the project and enjoy!
Remark: Why I need to hack the HEADER_SEARCH_PATHS: Originally it errors and says that protobuf headers cannot be found. This solution suggests that we add the paths manually by hand after each pod install. Moreover, this improved solution suggests that we can automate the process by adding a few lines of code. That is what we did above.
The alternative way
This link works pretty well basically. Although it is under the SDK tutorial of Cardboard, this webpage talks about almost nothing about Cardboard-specific things but only protobuf. Thus, feel free to follow it. After all steps except the last step ("copying files"), you will get: include/google/* and lib/libprotobuf-lite.a.
Before getting started, do not forget make distclean to clean everything (if you have already done something).
Remark 1: If you see errors when linking, saying "Undefined symbols" and "ld: warning: ignoring file", you may follow this link to solve it.
Remark 2: That tutorial only creates libprotobuf-lite.a. If you need libprotobuf.a, it can be done by analogy: lipo $build_dir/arch/arm64/lib/libprotobuf.a $build_dir/arch/armv7/lib/libprotobuf.a -create -output $build_dir/lib/libprotobuf.a.
Then, you can put the .a and the headers into your ios xcode project. I have not tried this yet, because I use the approach above.
Android
Get lib and headers
It is a little bit more complex than iOS.
Before getting started, do not forget make distclean to clean everything (if you have already done something).
Firstly, follow the same link as the approach to generating your own .a and headers in iOS to do git clone, git checkout, git submodule and ./autogen.sh, but stop there and do not continue.
Next, you need to follow this answer to hack the code a little bit - otherwise the compilation will fail. Please refer to the link to do a patch using ltmain.sh.patch. (As for the fuse-ld flag I already do it, so no need for you to do anything.)
Now comes the configure and compile, which goes as follows.
export NDKDIR=/Users/tom/Library/Android/sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/darwin-x86_64
export SYSROOT=$NDKDIR/sysroot
./configure \
--prefix=/Users/tom/RefCode/libprotobuf/android \
--host=arm-linux-androideabi \
--with-sysroot="${SYSROOT}" \
--enable-shared \
--enable-cross-compile \
--with-protoc=protoc \
"CC=$NDKDIR/bin/armv7a-linux-androideabi26-clang" \
CFLAGS="-fPIC -fuse-ld=bfd -march=armv7-a -D__ANDROID_API__=26" \
"CXX=$NDKDIR/bin/armv7a-linux-androideabi26-clang++" \
CXXFLAGS="-fPIC -fuse-ld=bfd -frtti -fexceptions -march=armv7-a -D__ANDROID_API__=26" \
"RANLIB=$NDKDIR/bin/x86_64-linux-android-ranlib" \
"C_COMPILER_RANLIB=$NDKDIR/bin/x86_64-linux-android-ranlib" \
"CXX_COMPILER_RANLIB=$NDKDIR/bin/x86_64-linux-android-ranlib" \
"AR=$NDKDIR/bin/x86_64-linux-android-ar" \
LIBS="-llog -lz -lc++_static";
make -j8 && make install
Remark: The commands above is similar but not equal to this post, because the NDK standalone toolchain used in that post is deprecated already. Of course, you may need to change your versions, such as the path to your own ndk, your ndk version, etc.
Remark: You may also need to know the naming conventions used above. For example, why sometimes it is llvm, why sometimes it is darwin, and why armv7a. They are described in detail in the official guide.
Remark: this link is also useful when you face problem of libprotobuf.a: no archive symbol table (run ranlib) when compiling your android app using Gradle.
Remark: Without -fPIC, errors like requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC will occur. So I followed this link to address it.
Remark: If you see errors such as error: undefined reference to 'stderr', you may need to make your minSdkVersion bigger, such as changing to 23. ref
Remark: After changing things, multiple cleaning may be needed. For example, gradle sync, gradle clean, make distclean, etc.
Similar to the guide, the next step is make -j8 and then make install. Then you are done and will see some libs like libprotobuf-lite.a as well as include headers.
Use it in your project
Add the following to CMakeLists.txt:
set(OPENCV_BASE_DIR "/some/absolute/path/to/your/base/dir/that/has/built/just/now")
message("PROTOBUF_BASE_DIR: ${PROTOBUF_BASE_DIR}")
set(PROTOBUF_INCLUDE_DIR "${PROTOBUF_BASE_DIR}/include/")
set(PROTOBUF_STATIC_LIB_DIR "${PROTOBUF_BASE_DIR}/lib")
if (NOT EXISTS ${PROTOBUF_INCLUDE_DIR})
message(FATAL_ERROR "PROTOBUF_INCLUDE_DIR=${PROTOBUF_INCLUDE_DIR} does not exist - have you provided the correct PROTOBUF_BASE_DIR=${PROTOBUF_BASE_DIR}")
endif ()
include_directories(${PROTOBUF_INCLUDE_DIR})
add_library(protobuf-lite STATIC IMPORTED)
set_target_properties(protobuf-lite PROPERTIES IMPORTED_LOCATION ${PROTOBUF_STATIC_LIB_DIR}/libprotobuf-lite.a)
add_library(protobuf STATIC IMPORTED)
set_target_properties(protobuf PROPERTIES IMPORTED_LOCATION ${PROTOBUF_STATIC_LIB_DIR}/libprotobuf.a)
target_link_libraries(yourapp
...others...
protobuf
)
Since I only build for armv7 instead of armv8 in the code above, we can add an abi filter as follows. Or, alternatively, you can also build for armv8 and merge them into a fat lib just like what we have done in ios.
build.gradle:
android {
defaultConfig {
externalNativeBuild {
cmake {
abiFilters 'armeabi-v7a'
}
}
}
}
Bonus: MacOS
Get lib and headers
What if you want to also use your C++ code (with protobuf) on your mac computer?
Before getting started, do not forget make distclean to clean everything (if you have already done something).
Similar to this link, you only need to change your ./configure to:
./configure CC=clang CXX="clang++ -std=c++11 -stdlib=libc++" CXXFLAGS="-O3" --disable-shared
and the other things are remained almost the same as the guide, such as downloading, configuring, make and finally sudo make install (notice you need sudo here).
You will see headers in your system's include directory and libs in your system's lib folder.
Use it in your project
If you are using CMake, it is mostly standard. Firstly, add path/to/your/hello.pb.cc into your add_executable. Secondly, add /usr/local/lib/libprotobuf.a to your target_link_libraries. Full example:
add_executable(app
./main.cpp
path/to/your/hello.pb.cc
... others ...
)
target_link_libraries(app
/usr/local/lib/libprotobuf.a
... others ...
)
Remark: libprotobuf-lite.a sometimes does not suffice, so you need to link with the big lib instead of the lite lib.
I tried to build android-vlc and ijkPlayer using Git, and after following the steps and making the required sdk and ndk exports for each one, both lead me to the same error message through Git-Bash which is:
You need NDKr9 or later
I have NDKr9b and NDKr10d and I got this error message with both of them, and after having a look at android-vlc sdk source code I found that it just checking the /RELEASE.TXT file in the ndk provided path:
# try to detect NDK version
REL=$(grep -o '^r[0-9]*.*' $ANDROID_NDK/RELEASE.TXT 2>/dev/null|cut -b2-)
case "$REL" in
9*|10*)
GCCVER=4.8
CXXSTL="/"${GCCVER}
;;
7|8|*)
echo "You need the NDKv9 or later"
exit 1
;;
esac
and when checking it my self for NDK10, I found that it only contains one line which is:
r10d (64-bit)
and in NDK9 it is:
r9b
which supposed to make the code run without problems in both cases, so what am I missing here?
p.s. I came across this question which provides the same problem but it's answer doesn't work with me.
Swiften is a XMPP client library and my objective was to build it for a ARM-embedded target running Linux.
I hacked my way to a successful cross-compile with little knowledge of SCons. I'll lay out my hack here with the hope that someone can point me to a maintainable solution using the two makery files, SConscript.boot and SConstruct.
I had two tasks (neither accomplished satisfactorily):
Successfully switching the tool-chain from native-compile to cross-compile
Ensuring that OpenSSL libraries were successfully linked (not supplied by the swiftim project; they has to be installed and built in the 3rdParty folder).
Switching the tool-chain from native-compile to cross-compile for ARM
My ARM cross tool-chain components, gcc, g++, ld, etc are located here.
/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/arm-linux-gnueabihf/bin/
I couldn't find a way to tell scons to use the cross tool-chain (from the above location) instead of the native tool (in the usual place, /usr/bin). Prefacing the invocation (./scons Swiften) with the fully-qualified values for the environment variables, CC and CXX didn't work (while not recommended, its alluded to in one place).
Scons would only pick up the native tool-chain even after many ad hoc changes to the makery.
So, as a hack, I had to change the native tool-chain to point to the cross tool-chain.
/usr/bin/gcc -> /opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/bin/arm-linux-gnueabihf-gcc-4.7.3*
/usr/bin/g++ -> /opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/bin/arm-linux-gnueabihf-g++*
The first compile-break for ARM was fixed by adding the line below to the default portion of the build script, SConscript.boot.
env.Append(CPPDEFINES = ["_LITTLE_ENDIAN"])
The next compile-break has to do with the OpenSSL header files not being found. To fix the location issue, I had to introduce the line below into SConscript.boot
vars.Add(PackageVariable("openssl", "OpenSSL location", "/home/auro-tripathy/swiftim/swift/3rdParty/OpenSSL/openssl-1.0.1c/"))
Linking with OpenSSL
For the sample Switften programs to link with the OpenSSL libraries, I had to move libssl.a and libcrypto.a (built separately) from the location they were built to the toolchain library-location like so.
mv ~/swiftim/swift/3rdParty/OpenSSL/openssl-1.0.1c/libcrypto.a /opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/lib/gcc/arm-linux-gnueabihf/4.7.3/.
Help
Not understanding of the working of scons, I've made some hacks to get it to work.
I’d like some help to:
Introduce a new target called ARM-embedded, just like other targets; iPhone, android, etc
Clean way to integrate OpenSSL into the build .
Update
Per dirkbaechle, retried the script below and it works
export CC=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/arm-linux-gnueabihf/bin/gcc
export CXX=/opt/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7-2013.01-20130125_linux/arm-linux-gnueabihf/bin/g++
./scons Swiften
Brady's answer is correct, regarding how you'd do it in plain SCons. I'd just like to mention that the top-level SConstruct of Swiften already provides arguments like "cc=" and "cxx=" for using local toolchains.
You might want to inspect the ouput of scons -h for a complete list of available options.
In addition, the SConscript for the OpenSSL build expects the sources to be located in the relative folder named "openssl", not "openssl-1.0.1c" as in your case. Maybe that's where your build problems are mainly coming from.
I left a comment above regarding the cross-compilation. Its already been answered in the link provided, but basically you just need to set the appropriate construction variables: CC, CXX, LINK, etc.
As for a "Clean way to integrate OpenSSL into the build" this can be performed simply by adding library and include paths appropriately as follows replacing the quoted values appropriately:
(without having to copy/move the original files)
# This sets the location of the OpenSSL Include paths
env.Append(CPPPATH="path/to/openssl/includes")
# This sets the location of the OpenSSL Libraries
env.Append(LIBPATH="path/to/openssl/libraries")
# These are the OpenSSL libraries to be linked into the binary
env.Append(LIBS=["OpenSSL_lib", "OpenSSL_lib2"])
The choice of compiler, and additional flags, can all be set in Swift's config.py file. A snippet from config.py using a custom compiler and flags is below (the one I use on one of my dev boxes):
cc = link = "/usr/local/llvm-git/bin/clang"
cxx = "/usr/local/llvm-git/bin/clang++"
bothflags = " -std=c++11 -stdlib=libc++ -nostdinc++"
cxxflags = bothflags + " -I/usr/local/libcxx/include -Wno-deprecated"
linkflags = bothflags + " -L/usr/local/libcxx/lib"
This should work for cross-compiling in the same manner.
To use a bundled openssl, you should just be able to extract into 3rdParty/OpenSSL, and add openssl_force_bundled = True to your config.py. You should not need to fiddle with setting include paths to this yourself. It's conceivable that this is tied to a particular openssl release as I've not compiled a bundled openssl since 1.0.0a, but if it doesn't work with the current version it's probably a bug that ought to be fixed. You could also cross-compile openssl yourself and use openssl='/path/to/openssl', but that's a little more of a nuisance for you.
I want to convert pdf to pksmraw by using ghostscript9.04, the command is:
gs -q -dBATCH -dSAFER -dQUIET -dNOPAUSE -sPAPERSIZE=a4 -r300x300 -sDEVICE=pksmraw -sOutputFile=printjob.pksmraw printjob.pdf
But in android system, it's no output, and the error code is -15.
I think it's maybe Resources and libs is can't be found.
So in android system, how to set up the Resources and libs?
error code -15 is a rangecheck error. In order to find out more you are going to have to find out where stdout and stderr are going, and capture them.
We don't supply Ghostscript for Android systems, so I assume you built this yourself, in which case it should be reasonably straight-forward for you to figure out where the error messages are going.
Oh, the current version is 9.10, you might well want to upgrade too.
Library and resource files are ordinarily built into the executable using a rom file system, unless you specified COMPILE_INITS=0 at build time.
Try this example
gs \
-sDEVICE=pdfwrite \
-o foo.pdf \
/usr/local/share/ghostscript/8.71/lib/viewjpeg.ps \
-c \(my.jpg\) viewJPEG
reads my.jpg and produces foo.pdf. You will have to find where your installation installed the PostScript program viewjpeg.ps.
Same way do it for to convert pdf to pksmraw it will work for you.