different ways of compilation cause the same dynamic library generate differents results - c

I use different ways of compilation to compile my project for testing symbol of a same cover when loaded dynamic library, however, there are two different results in different compilations, I cannot find differences between this two compilations, please help?
when I use dlopen() and dlsym(), I see official description of dlsym() as below:
The dlsym() function shall search for the named symbol in all objects
loaded automatically as a result of loading the object referenced by
handle (see dlopen()). Load ordering is used in dlsym() operations
upon the global symbol object. The symbol resolution algorithm used
shall be dependency order as described in dlopen().
Note: load ordering is an mechanism to handle conflict when loaded symbols with same name.
So I want to run a test for load ordering, however, I find different results when use different compilations(as I think two of them are equivalent)
here is my project:
file tree:
├── CMakeLists.txt
├── fn.c
└── main.c
CMakeLists.txt
project(demo)
set(CMAKE_CXX_FLAGS " -fpic ${CMAKE_CXX_FLAGS}")
add_library(fn SHARED fn.c)
add_executable(demo main.c)
target_link_libraries(demo -ldl)
fn.c
#include<stdio.h>
int temp = 1;
void fn_print(){
printf("fn temp address is %p, value is %d\n", &temp, temp);
}
main.c
#include<stdio.h>
#include<dlfcn.h>
typedef void (*fn_p)();
int temp = 0;
int main(){
printf("main temp address is %p, value is %d\n", &temp, temp);
void *handle = dlopen("./libfn.so", RTLD_NOW);
fn_p dy_print = dlsym(handle, "fn_print");
dy_print();
return 0;
}
First, I use cmake to compile this project and test, we can see variable temp share the same address 0x60104c and value 0 in obj file and dynamic library.
root#acnszavl00033:~/temp/dylib_test# cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /root/temp/dylib_test
root#acnszavl00033:~/temp/dylib_test# make
Scanning dependencies of target demo
[ 25%] Building C object CMakeFiles/demo.dir/main.c.o
[ 50%] Linking C executable demo
[ 50%] Built target demo
Scanning dependencies of target fn
[ 75%] Building C object CMakeFiles/fn.dir/fn.c.o
[100%] Linking C shared library libfn.so
[100%] Built target fn
root#acnszavl00033:~/temp/dylib_test# ./demo
main temp address is 0x60104c, value is 0
fn temp address is 0x60104c, value is 0
according to description, varaible temp should have different addresses, then I use gcc to only recompile demo(don't make changes to dynamic library libfn.so) , then test, varaible temp have different addresses, why?
root#acnszavl00033:~/temp/dylib_test# gcc -o demo main.c -ldl
root#acnszavl00033:~/temp/dylib_test# ./demo
main temp address is 0x60104c, value is 0
fn temp address is 0x7f795cec0028, value is 1
I expect output of compilatoin using cmake should like this:
main temp address is 0x60104c, value is 0
fn temp address is 0x7f795cec0028, value is 1

The below CMakeLists.txt seems to solve the issue:
cmake_minimum_required(VERSION 3.4)
project(demo)
add_library(fn SHARED fn.c)
add_executable(demo main.c)
target_link_libraries(demo PRIVATE dl)
When you don't add cmake_minimum_required or just provide anything below VERSION 3.4, you have the problem. Otherwise, when you build and run, you get the following:
~/so/build> cmake ..
-- The C compiler identification is GNU 9.1.0
-- The CXX compiler identification is GNU 9.1.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/aytekin/so/build
~/so/build> cmake --build .
Scanning dependencies of target fn
[ 25%] Building C object CMakeFiles/fn.dir/fn.c.o
[ 50%] Linking C shared library libfn.so
[ 50%] Built target fn
Scanning dependencies of target demo
[ 75%] Building C object CMakeFiles/demo.dir/main.c.o
[100%] Linking C executable demo
[100%] Built target demo
~/so/build> ./demo
main temp address is 0x56135a414044, value is 0
fn temp address is 0x7f170b3cb028, value is 1
I am not sure if this has to do with the policy change introduced in v3.4, but the most relevant change seems to be CMP0065.

Related

WIN32 and UNIX don't change in CMake cross-compile

I made a test CMakeLists.txt. I set system name and version before reading variables (although I didn't set the compiler):
cmake_minimum_required(VERSION 3.10)
project(test)
include_directories(.)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0.10240.0)
add_executable(test test.c)
target_link_libraries(test)
message("cmake system name = ${CMAKE_SYSTEM_NAME}")
message("cmake host name = ${CMAKE_HOST_SYSTEM_NAME}")
message("cmake system version = ${CMAKE_SYSTEM_VERSION}")
message("unix = ${UNIX}")
message("win32 = ${WIN32}")
Here is the output from "cmake ." on the terminal:
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
cmake system name = Windows
cmake host name = Linux
cmake system version = 10.0.10240.0
unix = 1
win32 =
-- Configuring done
-- Generating done
-- Build files have been written to: /home/francisco/Documents
The CMake documentation says UNIX and WIN32 are set to the target OS. Here I set the target OS and yet they remain set to the host OS. Why?
You're not supposed to write CMAKE_SYSTEM_NAME after the first project() command is encountered by CMake. At the first project command the choices of compiler and target system are made and you cannot change the effects of this later. As you have seen you can overwrite the value of CMAKE_SYSTEM_NAME, but the only effect of doing this are that you and any external cmake logic that may be invoked (e.g. scripts executed when using find_package) see a value that is wrong (i.e. not matching the choice of compiler).
For setting this kind of information your CMakeLists.txt files are the wrong place. This kind of info belongs into a toolchain file alongside your choice of compiler that actually produces binaries for the target platform:
toolchain-windows.cmake
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0.10240.0)
set(CMAKE_C_COMPILER <command/absolute path to executable to use as C compiler goes here>)
set(CMAKE_CXX_COMPILER <command/absolute path to executable to use as C++ compiler goes here>)
...
Configure the project using something like
cmake --toolchain path/to/toolchain-windows.cmake -S path/to/source -B path/to/build/dir
Note: The default compiler on your linux almost certainly won't be able cross compile for windows targets.

CMake Produces Makefile that Linker Doesn't Like

I'm trying to modernize a build system with CMake. When I try to compile the program with make I get this output
$ cmake -DCMAKE_TOOLCHAIN_FILE="../armgcc.cmake" .. && make
-- The C compiler identification is GNU 9.2.1
-- The CXX compiler identification is GNU 9.2.1
-- Check for working C compiler: /usr/bin/arm-none-eabi-gcc
-- Check for working C compiler: /usr/bin/arm-none-eabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/arm-none-eabi-g++
-- Check for working CXX compiler: /usr/bin/arm-none-eabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: ~/cmake_test/build
Scanning dependencies of target testproj
[ 50%] Building C object CMakeFiles/testproj.dir/main.c.obj
[100%] Linking C executable testproj
arm-none-eabi-gcc: fatal error: /usr/lib/gcc/arm-none-eabi/9.2.1/../../../arm-none-eabi/lib/nosys.specs: attempt to rename spec 'link_gcc_c_sequence' to already defined spec 'nosys_link_gcc_c_sequence'
compilation terminated.
make[2]: *** [CMakeFiles/testproj.dir/build.make:84: testproj] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/testproj.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
With CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(testproj VERSION 0.1.0)
add_executable(testproj main.c)
and armgcc.cmake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nosys.specs")
What are link_gcc_sequence and nosys_link_gcc_sequence, and how should I structure my CMakeLists to avoid renaming them?

Cmake add library to a custom gcc compiler

I'm trying to compile a small program written in c with additional libraries zlib and libpng for an arm processor using using gcc-linaro-arm-linux.
In some .c file:
#include <bzlib.h>
If I compile with an ordinary gcc, everything is working fine, but with a gcc-linaro-arm-linux compiler it could not find libraries:
cmake:
$cmake -D CMAKE_C_COMPILER="${HOME}/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/arm-linux-gnueabihf-gcc" -D CMAKE_CXX_COMPILER="${HOME}/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/arm-linux-gnueabihf-g++" CMakeLists.txt
-- The C compiler identification is GNU 4.8.3
-- The CXX compiler identification is GNU 4.8.3
-- Check for working C compiler: /home/alex/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/arm-linux-gnueabihf-gcc
-- Check for working C compiler: /home/alex/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/arm-linux-gnueabihf-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /home/alex/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/arm-linux-gnueabihf-g++
-- Check for working CXX compiler: /home/alex/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.03_linux/bin/arm-linux-gnueabihf-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Could NOT find ZLIB (missing: ZLIB_LIBRARY) (found version "1.2.8")
CMake Error at /usr/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:108 (message):
Could NOT find PNG (missing: PNG_LIBRARY PNG_PNG_INCLUDE_DIR)
Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:315 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake-2.8/Modules/FindPNG.cmake:105 (find_package_handle_standard_args)
src/CMakeLists.txt:3 (find_package)
You need to tell CMake where to find your target sysroot. Check out CMAKE_FIND_ROOT_PATH.

CMake not compile on raspberry

I'm new with cmake.
With cmake I was able to compile my project on my laptop, but on the raspberry is not working.
This is the error i get on raspberry:
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.28")
-- checking for one of the modules 'glib-2.0'
-- Found GLib: /usr/lib/arm-linux-gnueabihf/libglib-2.0.so (found version "2.42.1")
-- Found mhd: /usr/include
CMake Error at cmake/FindGLIB.cmake:39 (add_library): add_library cannot create imported target "glib-2.0" because another target with the same name already exists.
Call Stack (most recent call first):librerie/CMakeLists.txt:2 (find_package)
-- Found GLib: /usr/lib/arm-linux-gnueabihf/libglib-2.0.so (found version "2.42.1")
-- Configuring incomplete, errors occurred!
See also "/home/pi/pl1/CMakeFiles/CMakeOutput.log".
This is my project structure:
src->
---- CMakeLists.txt
---- main.c
---- librerie->
-------------- CMakeLists.txt
-------------- cJSON.c
-------------- cJSON.h
-------------- config.c
-------------- config.h
-------------- server_web.c
-------------- server_web.h
-------------- funzioni_thread.c
-------------- funzioni_thread.h
---- cmake->
-------------- FindGLIB.cmake
-------------- FindMHD.cmake
This is First CMakeLists :
cmake_minimum_required (VERSION 2.6)
project (TestPL)
include_directories("${PROJECT_BINARY_DIR}")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(GLIB REQUIRED)
find_package(MHD REQUIRED)
add_subdirectory (librerie)
set (EXTRA_LIBS ${EXTRA_LIBS} librerie)
include_directories (${GLib_INCLUDE_DIRS} ${EXTRA_LIBS})
# add the executable
add_executable(TestPL main.c)
target_link_libraries (TestPL ${GLib_LIBRARY} ${MHD_LIBRARY} ${EXTRA_LIBS} m)
This is CMakeLists in librerie directory:
find_package(GLIB REQUIRED)
find_package(MHD REQUIRED)
include_directories (${GLib_INCLUDE_DIRS} ${EXTRA_LIBS})
add_library (librerie cJSON.c config.c generic.c server_web.c funzioni_thread.c)
target_link_libraries (librerie ${GLib_LIBRARY} ${MHD_LIBRARY})
What am I doing wrong?
You call twice
find_package(GLIB REQUIRED)
First time it is called from top-level CMakeLists.txt and defines glib-2.0 target. Second time it is called from librerie/CMakeLists.txt and attempt to create glib-2.0 again. That is why you see that error message: the target is already defined in this scope.
Possible workaround is to step into library subdirectory first, and only then call find_package() in top-level CMakeLists.txt:
add_subdirectory (librerie)
find_package(GLIB REQUIRED)
find_package(MHD REQUIRED)
Because IMPORTED targets has local visibility, glib-2.0 target defined by find_package(GLIB) call from subdirectory librerie/ will not be visible after returning from this subdirectory. So the second call from top-level directory will succeed.

cmake doesn't display display message

Fedora 15
cmake version 2.8.4
I am using the following CMakeLists.txt. However the status message doesn't display when I run cmake .
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(proj2 C)
IF(CMAKE_COMPILER_IS_GNUCXX)
MESSAGE(STATUS "==== GCC detected - Adding compiler flags")
SET(CMAKE_C_FLAGS "-pthread -ggdb -Wextra -Wall")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
ADD_EXECUTABLE(crypto_app main.c)
TARGET_LINK_LIBRARIES(crypto_app crypt)
All I get is the following:
-- The C compiler identification is GNU
-- Check for working C compiler: /usr/lib64/ccache/gcc
-- Check for working C compiler: /usr/lib64/ccache/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/projects/proj1/
Many thanks for any suggestions about this.
You're telling cmake that it's a C project, and then checking for a CXX (i.e. C++) compiler. CMAKE_COMPILER_IS_GNUCXX will never be true in this case. That's why.

Resources