NDK 25 Did not add optimized level in Build Type Release with CMake - cmake

I'm working on a shared library with CMake. Today I try to build it with NDK 25. when build type is "DEBUG", cmake add -O0 in CXX_FLAGS, and it add "-O2" in "RELWITHDEBINFO" build type. but when I changed it to "RELEASE", no optimize level was set.
I looked into the files that CMake generated. I found this in "CMakeCache.txt":
//Flags used by the compiler during all build types.
CMAKE_CXX_FLAGS:STRING=
//Flags used by the compiler during debug builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=
//Flags used by the CXX compiler during MINSIZEREL builds.
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
//Flags used by the compiler during release builds.
CMAKE_CXX_FLAGS_RELEASE:STRING=
//Flags used by the CXX compiler during RELWITHDEBINFO builds.
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
//Libraries linked by default with all C++ applications.
CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm
I found "CMAKE_CXX_FLAGS_RELEASE:STRING" is empty, that's why optimize level is not set when buildding "RELEASE".
This is my shell script to run the cmake:
NDK_PATH="~/Library/Android/sdk/ndk/25.0.8775105"
rm -rf buildV7
mkdir buildV7
cd buildV7
../../../../CMake/Mac/CMake.app/Contents/bin/cmake ..
-DANDROID_ABI=armeabi-v7a
-DANDROID_PLATFORM=android-23
-DANDROID_NDK=$NDK_PATH
-DCMAKE_BUILD_TYPE=RELEASE
-DCMAKE_TOOLCHAIN_FILE=$NDK_PATH/build/cmake/android.toolchain.cmake
make VERBOSE=1
cd ..
the final clang command is:
Android/sdk/ndk/25.0.8775105/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=armv7-none-linux-androideabi23 --sysroot=Android/sdk/ndk/25.0.8775105/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -DBianqueLogger_EXPORTS -I/Users/TestProj/build/android/dynamicLib/../../../src -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -DNDEBUG -fPIC -std=gnu++11 -MD -MT CMakeFiles/BianqueLogger.dir/Users/TestProj/src/utils/head.cpp.o -MF CMakeFiles/BianqueLogger.dir/Users/TestProj/src/utils/head.cpp.o.d -o CMakeFiles/BianqueLogger.dir/Users/TestProj/src/utils/head.cpp.o -c /Users/TestProj/src/utils/head.cpp
Is This NDK's BUG? Or -O3 is no longer needed in NDK25 and it's clang toolchain?

https://github.com/android/ndk/issues/1740. Will be fixed in r25b.
But typically you don't want to use Release for Android, you want to use RelWithDebInfo or MinSizeRel (it's really unfortunate that cmake doesn't have a MinSizeRelWithDebInfo). Your packaging tools should be stripping any libraries before packing them into an APK, so there is no reason to avoid compiling debug info. All that does is make it so you can't debug.

"Release" - there is no such config by default in NDK since r23. The default configs are: "Debug", "MinSizeRel" and "RelWithDebInfo". Use one of these three.

Related

Why Autotools Ignores Installed Static Library?

I have installed ROHC library (http://rohc-lib.org) using following commands during installation:
autoreconf -if
./configure --enable-static=yes --enable-shared=no --disable-shared --prefix=/usr
make
make install
It successfully installed static (and only static) libraries in /usr/lib directory. It contains librohc.a and librohc.la and no shared-library (i.e. librohc.so*).
I am trying to link this library with OpenVPN. I added following lines in configure.ac of OpenVPN:
AC_CHECK_HEADERS(
[rohc/rohc.h rohc/rohc_comp.h rohc/rohc_decomp.h],
,
[AC_MSG_ERROR([ROHC headers not found])]
)
AC_CHECK_LIB(
[rohc],
[rohc_compress4],
,
[AC_MSG_ERROR([ROHC library not found])]
)
But when I run make in OpenVPN source directory, I get the following error:
/bin/sh ../../libtool --tag=CC --mode=link gcc -DPLUGIN_LIBDIR=\"/usr/local/lib/openvpn/plugins\" -Wall -Wno-unused-parameter -Wno-unused-function -g -O2 -std=c99 -lrt -o openvpn argv.o base64.o buffer.o clinat.o comp.o compstub.o comp-lz4.o crypto.o crypto_openssl.o crypto_mbedtls.o dhcp.o error.o event.o fdmisc.o forward.o fragment.o gremlin.o helper.o httpdigest.o lladdr.o init.o interval.o list.o lzo.o manage.o mbuf.o misc.o platform.o console.o console_builtin.o console_systemd.o mroute.o mss.o mstats.o mtcp.o mtu.o mudp.o multi.o ntlm.o occ.o pkcs11.o pkcs11_openssl.o pkcs11_mbedtls.o openvpn.o options.o otime.o packet_id.o perf.o pf.o ping.o plugin.o pool.o proto.o proxy.o ps.o push.o reliable.o route.o schedule.o session_id.o shaper.o sig.o socket.o socks.o ssl.o ssl_openssl.o ssl_mbedtls.o ssl_verify.o ssl_verify_openssl.o ssl_verify_mbedtls.o status.o tls_crypt.o tun.o win32.o rohc.o trunk.o cryptoapi.o ../../src/compat/libcompat.la -lnsl -lresolv -llzo2 -llz4 -lssl -lcrypto -ldl -lrohc
libtool: link: gcc -DPLUGIN_LIBDIR=\"/usr/local/lib/openvpn/plugins\" -Wall -Wno-unused-parameter -Wno-unused-function -g -O2 -std=c99 -o openvpn argv.o base64.o buffer.o clinat.o comp.o compstub.o comp-lz4.o crypto.o crypto_openssl.o crypto_mbedtls.o dhcp.o error.o event.o fdmisc.o forward.o fragment.o gremlin.o helper.o httpdigest.o lladdr.o init.o interval.o list.o lzo.o manage.o mbuf.o misc.o platform.o console.o console_builtin.o console_systemd.o mroute.o mss.o mstats.o mtcp.o mtu.o mudp.o multi.o ntlm.o occ.o pkcs11.o pkcs11_openssl.o pkcs11_mbedtls.o openvpn.o options.o otime.o packet_id.o perf.o pf.o ping.o plugin.o pool.o proto.o proxy.o ps.o push.o reliable.o route.o schedule.o session_id.o shaper.o sig.o socket.o socks.o ssl.o ssl_openssl.o ssl_mbedtls.o ssl_verify.o ssl_verify_openssl.o ssl_verify_mbedtls.o status.o tls_crypt.o tun.o win32.o rohc.o trunk.o cryptoapi.o ../../src/compat/.libs/libcompat.a -lrt -lnsl -lresolv -llzo2 -llz4 -lssl -lcrypto -ldl /usr/lib/librohc.so
gcc: /usr/lib/librohc.so: No such file or directory
Yes, /usr/lib/librohc.so does not exist, but /usr/lib/librohc.a exists. Why is it not linking with the static library /usr/lib/librohc.a at absence of .so ?
You may ask me why I am not installing shared libs of ROHC; answer is that I want to force static linking with ROHC, and when it is done I will uninstall ROHC libs.
If someone could show me how to do this static linking without installing ROHC first (like adding dependency to configure.ac or Makefile.am of OpenVPN), it would be better for me.
Note that, both OpenVPN and ROHC library require autotools.
I specified --libdir=/usr/lib64 with ./configure of ROHC library and finally the build system used the static library librohc.a when linking with OpenVPN. I installed ROHC with:
autoreconf -if
./configure --enable-static --disable-shared --prefix=/usr --libdir=/usr/lib64
make
make install
Now it installs the library as /usr/lib64/librohc.a and Compilation of OpenVPN successfully finds and links to it.
And surely, it took place in a 64 bit machine (CentOS 6). In a 32 bit environment (OpenWrt in a 32-bit MIPS router) where there is nothing like /usr/lib64, the problem in the question does not take place.

Is -std=c++2a necessary at link stage as well?

If I compile in two stages, using a particular language standard:
g++ -std=c++2a -c file1.cpp #compile source files
g++ -std=c++2a -c file2.cpp
g++ -std=c++2a file1.o file2.o -o program #link 'em
...can I leave the -std=c++2a out of the link command, or is it sometimes needed?
Version is gcc 10.
I guess you are compiling on Linux with a recent GCC. Be sure to read more about C++ and about your particular compiler (i.e. GCC 9 is not the same as GCC 10). Check with g++ --version what it is.
In practice you want to compile with warnings and debug information (in DWARF for GDB inside your ELF object files and executables), so use
g++ -std=c++2a -Wall -Wextra -g -c file1.cpp
and likewise for file2.cpp
Later (once your program is correct enough, e.g. has few bugs) you could want to ask the compiler to optimize it. So you could use
g++ -std=c++2a -Wall -Wextra -O3 -g -c file1.cpp
Practically speaking, you'll configure your build automation tool (e.g. GNU make or ninja) to run your compilation commands.
In rare cases, you could want to use link time optimizations. Then you need to both compile and link with g++ -std=c++2a -Wall -Wextra -O3 -g -flto and perhaps other options.
Be aware that link time optimization could almost double your build time.
You could also be interested by static analysis options of GCC 10 (or even by writing your own static analysis using GCC plugins).

Changed include path behaviour from CMake 2.8.x to 3.9.x

I have a fairly large cmake project that exhibits a compiler error when I use Makefiles generated by CMake 3.9.x:
Scanning dependencies of target client
[ 21%] Building C object
src/lib/client/CMakeFiles/client.dir/client.c.o
In file included from <command-line>:0:0:
/usr/include/stdc-predef.h:40:1: fatal error: compiler.h: No such file or directory
#endif
^
This works properly when using Makefiles generated by CMake 2.8.x. Digging in a bit, I can see that a change was made to the flags.make file generated by CMake between these two versions. The older version used to put -I (include) options in the C_FLAGS variable defined in that file:
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# compile C with /usr/lib64/ccache/cc
C_FLAGS = -Wall -Wextra -Werror -Wformat=2 -Wundef -mcx16 -Werror-implicit-function-declaration -Wno-unused-parameter -D_GNU_SOURCE -include compiler.h -D__BUG_OUT_AUX=pd_trc_ftl -Wstrict-prototypes -Wdeclaration-after-statement -Wno-tautological-compare -g -I/.../src/lib/client ... -fPIC
C_DEFINES = -DBUILD_NUMBER=\"whatever\" -DBUILD_VERSION=\"1.66.0\" -DCOMMIT_HASH=\"f9bf1c93682f\" -DPDDEBUG -D_FILE_OFFSET_BITS=64
In later versions of CMake the -I options are broken out into their own C_INCLUDES variable:
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.9
# compile C with /usr/lib64/ccache/cc
C_FLAGS = -Wall -Wextra -Werror -Wformat=2 -Wundef -mcx16 -Werror-implicit-function-declaration -Wno-unused-parameter -D_GNU_SOURCE -include compiler.h -D__BUG_OUT_AUX=pd_trc_ftl -Wstrict-prototypes -Wdeclaration-after-statement -Wno-tautological-compare -g -fPIC
C_DEFINES = -DBUILD_NUMBER=\"whatever\" -DBUILD_VERSION=\"1.66.0\" -DCOMMIT_HASH=\"f9bf1c93682f\" -DPDDEBUG -D_FILE_OFFSET_BITS=64
C_INCLUDES = -I/.../src/lib/client ...
However, in both cases, the including file - build.make - uses only the $(C_DEFINES) $(C_FLAGS), omitting the $(C_INCLUDES) in the newer model:
...
# Include the compile flags for this target's objects.
include src/lib/client/CMakeFiles/client.dir/flags.make
src/lib/client/CMakeFiles/client.dir/client.c.o: src/lib/client/CMakeFiles/client.dir/flags.make
src/lib/client/CMakeFiles/client.dir/client.c.o: ../src/lib/client/client.c
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/.../cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object src/lib/client/CMakeFiles/client.dir/client.c.o"
cd /.../cmake-build-debug/src/lib/client && /.../contrib/cc/cgcc.sh /.../cmake-build-debug /usr/lib64/ccache/cc sparse ON /.../client-project CMakeFiles/client.dir/client.c.o $(C_DEFINES) $(C_FLAGS) -o CMakeFiles/client.dir/client.c.o -c /.../src/lib/client/client.c
...
Is this a bug in CMake 3.9.x? Has anyone else experienced anything like this when upgrading CMake?
I believe it's possible that we've always done something wrong in our CMakeLists.txt files that just happened to work in the older versions, but that when we upgraded to CMake 3.9.x, suddenly the problem is manifest. Hoping someone has had this issue and figured out what they did wrong.
Thanks in advance!

CMake on Cygwin with clang not creating expected dll.a

I'm building a shared library and an application using that lib on Cygwin. With GCC CMake creates a .dll.a to use when linking. Switching to clang I get
[ 34%] Built target xxx_shared
make[2]: *** No rule to make target 'src/libxxx.dll.a', needed by 'xxx.exe'. Stop.
Is this a bug in the clang CMake extension?
I'm using cmake --version 3.3.2
Yes, it seems to be a bug in CMake. Running make VERBOSE=1 reveals that with GCC:
/usr/bin/c++.exe -g -shared -Wl,--enable-auto-import -o XXX -Wl,-Bstatic -lm -Wl,-Bdynamic -lstdc++ -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32
while with clang:
/usr/bin/clang++ -fPIC -g -shared -o XXX -Wl,-Bstatic -lm -Wl,-Bdynamic -lstdc++ -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32
So it seems that somehow clang++ does not get the -Wl,--enable-auto-import flag. Manually running the corrected clang++ command correctly creates the expected .dll.a allowing the rest of the build to proceed as expected.
Haven't figured out why this happens yet, though. At this point I can't decipher CMakes platform extensions, which seems to set this for GCC.
Update: I've reported this here.

libtool picks up 64-bit library when I tries to build 32-bit program

I have a GNU build system with autoconf-2.69, automake-1.14.1, libtool-2.4.2. I've configured with --host=i686-linux on a x86_64 RHEL6 host OS to build a 32-bit program. The libtool command seems to be:
/bin/sh ../libtool --tag=CXX --mode=link g++ -I/home/STools/RLX/boost/include/boost-1_44 -m32 -g3 -Wall -static -o engine engine-main.o ../components/librlxvm.la /home/STools/RLX/boost/include/boost-1_44/../../lib/libboost_program_options-gcc42-mt-1_44.a -lz -lpthread -ldl -lrt -ldl -lz -lm
But the real command is to search the 64-bit libraries not the 32-bit libraries as shown below:
libtool: link: g++ -I/home/STools/RLX/boost/include/boost-1_44 -m32 -g3 -Wall -o engine engine-main.o -L/home/robert_bu/src/gcc/gcc-4.2.2/build-x86_64/x86_64-unknown-linux-gnu/libstdc++-v3/src -L/home/robert_bu/src/gcc/gcc-4.2.2/build-x86_64/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs -L/home/robert_bu/src/gcc/gcc-4.2.2/build-x86_64/./gcc ../components/.libs/librlxvm.a /home/STools/RLX/boost/include/boost-1_44/../../lib/libboost_program_options-gcc42-mt-1_44.a /home/STools/RLX/gcc-4.2.2-x86_64/lib/../lib64/libstdc++.so -L/lib/../lib64 -L/usr/lib/../lib64 -lc -lgcc_s -lrt -ldl -lz -lm -pthread -Wl,-rpath -Wl,/home/STools/RLX/gcc-4.2.2-x86_64/lib/../lib64 -Wl,-rpath -Wl,/home/STools/RLX/gcc-4.2.2-x86_64/lib/../lib64
The --host config seems to have no effect. Is there anyway to tell libtool that 32-bit libraries are what we want?
It seems that libtool uses "CC", "CXX" to check the library search path. After I set CC to "gcc -m32", and CXX to "g++ -m32", it works. So libtool does not add "-m32" automatically even if I try to build a 32-bit program on a 64-bit system.
You're being hit by the problem of libtool .la files expansion. In particular libstdc++.la is being expanded for you to a full path rather than a simple -lstdc++.
My suggestion is to remove .la file from the SDK you're using (/home/STools). This way libtool can't assume things for you. Usually the ones you have in the system are fine, because the libraries are already in the search path, so it does not need to use -rpath or the full path to the .so file.
Depending on how well the SDK was crafted, this might or might not work correctly, so take it with a grain of salt.