linking with .o file - g++

I have a .o file lib.o that was already compiled and contains functions f and g.
I have a .cpp file main.cpp that uses functions f and g.
How do I properly use f and g in main.cpp and how do I compile main.cpp with lib.o?
I tried g++ main.cpp lib.o -o main -lirc
but I get the error:
main.cpp:(.text+0x18c): undefined reference to `f(unsigned short)'
main.cpp:(.text+0x1a8): undefined reference to `g(unsigned short)'

Related

Linking problems with yaml-cpp

I am trying to incorporate yaml-cpp into my project.
I have a "Demes" class where I need to parse a YAML file.
This is the relevant method in Demes.cpp:
#include "Demes.hpp"
void Demes::parse(const std::string& fileName)
{
YAML::Node test = YAML::LoadFile(fileName);
}
where Demes.hpp includes the yaml-cpp headers and declares the 'parse' method.
Building with make -VERBOSE=1 (as suggested by #Tsyvarev) gives:
[100%] Linking CXX executable momentspp
cd /home/gvbarroso/Devel/momentspp/build/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/momentspp.dir/link.txt --verbose=1
/usr/bin/c++ -std=c++20 -Weffc++ -Wshadow -Wall -Wextra -ffast-math -O3 -march=native CMakeFiles/momentspp.dir/Log.cpp.o CMakeFiles/momentspp.dir/PolymorphismData.cpp.o CMakeFiles/momentspp.dir/SumStatsLibrary.cpp.o CMakeFiles/momentspp.dir/Drift.cpp.o CMakeFiles/momentspp.dir/Migration.cpp.o CMakeFiles/momentspp.dir/Mutation.cpp.o CMakeFiles/momentspp.dir/Recombination.cpp.o CMakeFiles/momentspp.dir/Epoch.cpp.o CMakeFiles/momentspp.dir/Model.cpp.o CMakeFiles/momentspp.dir/OptimizationWrapper.cpp.o CMakeFiles/momentspp.dir/Demes.cpp.o CMakeFiles/momentspp.dir/main.cpp.o -o momentspp -Wl,-rpath,/home/gvbarroso/.local/lib: /home/gvbarroso/.local/lib/libbpp-phyl3.so.1.0.0 /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.74.0 /home/gvbarroso/.local/lib/libbpp-seq3.so.1.0.0 /home/gvbarroso/.local/lib/libbpp-core3.so.1.0.0
/usr/bin/ld: CMakeFiles/momentspp.dir/Demes.cpp.o: in function Demes::parse(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': Demes.cpp:(.text+0x4c): undefined reference to YAML::LoadFile(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)'
/usr/bin/ld: Demes.cpp:(.text+0x12c): undefined reference to `YAML::operator<<(std::ostream&, YAML::Node const&)'
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/momentspp.dir/build.make:277: src/momentspp] Error 1
make[2]: Leaving directory '/home/gvbarroso/Devel/momentspp/build'
make[1]: *** [CMakeFiles/Makefile2:125: src/CMakeFiles/momentspp.dir/all] Error 2
make[1]: Leaving directory '/home/gvbarroso/Devel/momentspp/build'
make: *** [Makefile:156: all] Error 2
I am using CMake to build my project, but I am still fairly unfamiliar with it.
EDIT: I forgot to mention that I have two CMakeLists.txt files, one inside src and the other inside the external build.
The start of my CMakeLists.txt file in the external build is:
cmake_minimum_required (VERSION 3.5.0)
project (momentspp CXX)
SET(CMAKE_CXX_FLAGS "-std=c++20 -Weffc++ -Wshadow -Wall -Wextra -ffast-math -O3 -march=native")
And the part of it where I look for yaml-cpp is:
FIND_PACKAGE(yaml-cpp REQUIRED)
IF(yaml-cpp_FOUND)
INCLUDE_DIRECTORIES(${yaml-cpp_INCLUDE_DIRS})
SET(LIBS {yaml-cpp_LIBRARIES})
MESSAGE("-- yaml-cpp libraries found here:")
MESSAGE(" includes: ${yaml-cpp_INCLUDE_DIRS}")
ENDIF()
My full CMakeLists.txt file inside src is:
SET(momentspp_CPP
Log.cpp
PolymorphismData.cpp
SumStatsLibrary.cpp
Drift.cpp
Migration.cpp
Mutation.cpp
Recombination.cpp
Epoch.cpp
Model.cpp
OptimizationWrapper.cpp
Demes.cpp
main.cpp
)
ADD_EXECUTABLE (momentspp ${momentspp_CPP})
SET(momentspp-targets momentspp)
FOREACH (target ${momentspp-targets})
TARGET_LINK_LIBRARIES(${target} ${BPP_LIBS_SHARED} ${BOOST_LIBS_SHARED} ${EIGEN3_LIBS_SHARED} ${yaml-cpp_LIBS_SHARED})
TARGET_LINK_LIBRARIES (${target} ${LIBS})
ENDFOREACH (target)
INSTALL(TARGETS ${momentspp-targets} DESTINATION ${CMAKE_INSTALL_BINDIR})
and this was working prior to the inclusion of yaml-cpp.
This feels like a rather complicated CMake set-up, but I am copying and editing it from a previous project where someone else helped me with it.
How can I fix the linking issue?
I tried looking similar questions around here, but couldn't get their solutions to work for me (apparently those people where not using CMake to build their projects).
Thank you,
Gustavo

Meson can't find static libs

I can compile my project by running
g++ main.cpp -l:libpj-x86_64-unknown-linux-gnu.a -lpthread -lm -luuid
or
g++ main.cpp /usr/local/lib/libpj-x86_64-unknown-linux-gnu.a -lpthread -lm -luuid
But when I try adding library with either one of:
meson.get_compiler('cpp').find_library('libpj-x86_64-unknown-linux-gnu.a')
meson.get_compiler('cpp').find_library('/usr/local/lib/libpj-x86_64-unknown-linux-gnu.a')
I'm getting error:
ERROR: C++ library 'libpj-x86_64-unknown-linux-gnu' not found
Solution was to add 'dirs' variable even tho file is in standard /usr/local/lib path and to remove .a extension.
cc.find_library('libpj-x86_64-unknown-linux-gnu', dirs: '/usr/local/lib/')
Later of course lib was available inside meson and was added to executable and tested.

Compiling a Fortran mex file with CMake

I have a Fortran project that I've compiled into mex. It has a bunch of Fortran files that have to be linked together, and some mex libraries. Using a Makefile like the one below, I was able to get this to work:
MEX=/opt/matlab/r2018a/bin/mex
FORTRAN = gfortran
FFLAGS = -c -fpic -fopenmp -Wall -O3 -fdefault-real-8 -fdefault-double-8
MEXLIBDIR = /opt/matlab/r2018a/sys/os/glnxa64
MEXLIB = -lgfortran -liomp5 -lirc -lsvml -limf
OBJS=\
file_a.o\
file_b.o\
all: file_a file_b mex
mex: mex_executable.F $(OBJS)
$(MEX) -v -O mex_exectuable.F $(OBJS) -L$(MEXLIBDIR) $(MEXLIB)
file_a: file_a.f
$(FORTRAN) $(FFLAGS) file_a.f
file_b: file_b.f
$(FORTRAN) $(FFLAGS) file_b.f
Since I'll have several projects like this, I'd like to put everything into a single CMake file.
So far, I have a CMakeLists.txt that looks something like this, inside a build directory:
cmake_minimum_required(VERSION 2.8)
project(MEX)
enable_language(Fortran)
find_package(Matlab REQUIRED MAIN_PROGRAM MX_LIBRARY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/")
# Assuming gfortran
set(CMAKE_Fortran_FLAGS "-c -fpic -Wall -O3 -fopenmp -fdefault-real-8 -fdefault-double-8")
include_directories(
${Matlab_INCLUDE_DIRS}
)
# Add modules with MEX to be built
add_subdirectory("${PROJECT_SOURCE_DIR}/Project1")
And inside the Project1 directory I have, another CMakeLists.txt:
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
## MEX functions
matlab_add_mex(
NAME mex_executable
SRC mex_executable.F *.f
)
target_link_libraries(mex_executable lgfortran liomp5 lirc lsvml limf )
When I run the CMake I get the error:
Cannot find source file:
*.f
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
What is the correct way to tell CMake to compile the Fortran files and link the correct mex libraries?
This error likely results from the arguments provided to the matlab_add_mex() command here:
matlab_add_mex(
NAME mex_executable
SRC mex_executable.F *.f
)
The SRC argument accepts a list of source files, and likely cannot resolve the *.f provided. It would be best to list each file individually:
matlab_add_mex(
NAME mex_executable
SRC mex_executable.F file_a.f file_b.f
)
Or, you can use CMake's GLOB to create a list of .f source files, and use that list instead:
file(GLOB FORTRAN_SRCS_LIST *.f)
matlab_add_mex(
NAME mex_executable
SRC mex_executable.F ${FORTRAN_SRCS_LIST}
)

linker error using static linking in g++

I am using other people's makefile and get troubles when trying to compile a 'static' version of the exe
I have printed out the makefile's rules and the error is like this:
g++ Main.or System.or Options.or -Wall -lz --static -o main
/usr/bin/ld: cannot find -lz
/usr/bin/ld: cannot find -lstdc++
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
If I do not include the '--static' option in the above command, it works fine.
The makefile also have rules to generate the static lib:
ar -rcsv lib_release.a Main.or System.or Options.or
r - Main.or
r - System.or
r - Options.or
Making Soft Link: lib_release.a -> lib.a
ln -sf lib_release.a lib.a
The -static linkage option instructs the linker to ignore all shared
libaries (libname.so) that could resolve the -lname linkage options (both explicit
and default) and accept only static libraries (libname.a). You have shared libraries installed on
your system that satisfy -lz, -lstdc++, -lm and -lc but no static ones.
For your linkage to work as it stands you must install the static libraries:
libz.a (Compression library)
libstdc++.a (The standard C++ library)
libm.a (The math library)
libc.a The standard C library
by the method that is appropriate to your distro.

"Link" to user32.dll in cmake when compile under Linux (cross)

I'm using mingw under Linux and I'm trying to compile for Windows. I'm using CMake and the ouptut should be an .exe file.
In my program I'm using a WinAPI call (RegisterPowerSettingNotification) which is found in user32.dll/user32.lib. I want to have my .exe independent of the user32.dll version (my .exe should run on Windows8/8.1/10).
My CmakeLists.txt:
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${USBHID_HEADER}
)
#USER32 // Will find the user32.lib
find_library(USER32 user32)
list(APPEND USBHID_LIB_DEPS ${USER32})
find_path(USBHID_HEADER winuser.h)
list(APPEND INCLUDES ${USBHID_HEADER})
# add the executable
add_executable( myexe win_service.c resource.rc )
target_link_libraries( myexe LINK_PUBLIC ${USBHID_LIB_DEPS} )
set_target_properties( myexe PROPERTIES OUTPUT_NAME "MyExeService" )
install( TARGETS myexe DESTINATION bin)
When I'm compiling, I'm receiving a warning:
/.../win_service.c:182:27: warning: assignment makes pointer from integer without a cast [enabled by default]
lidcloseRegHandle = RegisterPowerSettingNotification(serviceStatusHandle, &GUID_LIDCLOSE_ACTION,...
and at linking time:
Linking C executable myexeservice.exe
CMakeFiles/myexeservice.dir/objects.a(win_service.c.obj):win_service.c:(.text+0x393): undefined reference to `RegisterPowerSettingNotification'
collect2: error: ld returned 1 exit status
I know that linking against a DLL makes no sense, but how can I fool the CMake to not look after RegisterPowerSettingNotification?
RegisterPowerSettingNotification is available starting Windows Vista. Compiling with MinGW under Linux, by default WINVER is 0x502 (Windows Server 2003): /usr/share/mingw-w64/include/_mingw.h, RegisterPowerSettingNotification is not defined.
Solution is to add, before any
#include <windows.h>
the definition for WINVER and _WIN32_WINNT.
#ifndef WINVER
#define WINVER 0x0600
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif