How to generate a DLL linked to a static library with CMake - c++

The main objective with this question is to write an CMakeLists.txt to generate a dynamic library, "containing/linked" a static library.
Let me create the scenario:
My C++ code is written in mycode.cpp
In mycode.cpp, I call some functions from libthirdparty.a (static library)
I want to generate libmylib.so (shared library) to be dynamically linked by others
libmylib.so must to "contain" libthirdparty.a
My attempt to write this script is at the lines bellow:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror -m64 -fPIC ")
add_executable(myapp mycode.cpp)
target_link_libraries(myapp thirdparty)
add_library(mylib SHARED myapp)
But of course this is not working and I would like some help to write it correctly.

For now, let's remove the myapp and focus only on the library you are trying to create.
That said, here is what you could do
cmake_minimum_required(VERSION 3.12)
project(AwesomeLib)
include(GenerateExportHeader)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(ThirdParty REQUIRED)
add_library(mylib SHARED mylib.cpp)
target_link_libraries(mylib PUBLIC ThirdParty)
# Note: If you library will be cross-platform, flag should be conditionally specified. Have a look at generator-expression
target_compile_options(mylib PRIVATE -Wall -Werror)
generate_export_header(mylib)
# TODO:
# * add install rules
# * generate config-file package
# * add tests
Notes:
generate_export_header will generate "mylib_export.h" header with the MYLIB_EXPORT macro for exporting symbols. See https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html
to understand the idea behind find_package(ThirdParty REQUIRED), I recommend you read config-file package. See Correct way to use third-party libraries in cmake project
to learn more about generator expression. See https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html

Related

pybind11 and another libs in one project [duplicate]

I want to be able to call my C++ code as a python package. To do this I am using pybind11 with CMakelists (following this example https://github.com/pybind/cmake_example). My problem is that I have to include GSL libraries in the compilation of the code, and these need an explicit linker -lgsl .
If I were just to compile and run the C++ without wrapping it with python, the following Cmakelists.txt file does the job
cmake_minimum_required(VERSION 3.0)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
project(myProject)
add_executable(
myexecutable
main.cpp
function1.cpp
)
find_package(GSL REQUIRED)
target_link_libraries(myexecutable GSL::gsl GSL::gslcblas)
but when using pybind11 the template I found doesn't allow the add_executable therefore target_link_libraries doesn't work.
I have trie this
project(myProject)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES) # See below (1)
# Set source directory
set(SOURCE_DIR "project")
# Tell CMake that headers are also in SOURCE_DIR
include_directories(${SOURCE_DIR})
set(SOURCES "${SOURCE_DIR}/functions.cpp")
# Generate Python module
add_subdirectory(lib/pybind11)
pybind11_add_module(namr ${SOURCES} "${SOURCE_DIR}/bindings.cpp")
FIND_PACKAGE(GSL REQUIRED)
target_link_libraries(GSL::gsl GSL::gslcblas)
but this produces errors in the building.
Any idea ?
Function pybind11_add_module creates a library target, which can be used for link added module with other libraries:
pybind11_add_module(namr ${SOURCES} "${SOURCE_DIR}/bindings.cpp")
target_link_libraries(namr PUBLIC GSL::gsl GSL::gslcblas)
This is explicitely stated in documentation:
This function behaves very much like CMake’s builtin add_library (in fact, it’s a wrapper function around that command). It will add a library target called <name> to be built from the listed source files. In addition, it will take care of all the Python-specific compiler and linker flags as well as the OS- and Python-version-specific file extension. The produced target <name> can be further manipulated with regular CMake commands.

Build many subproject that can be built independently and use common CMake variable by CMake?

I want to give examples to some users of my project. The exmaple is to be used CMake. And It's like:
- top level
CMakeLists.txt
-- example A
A.cpp
CMakeLists.txt
-- example B
B.cpp
CMakeLists.txt
-- example C
C.cpp
CMakeLists.txt
I want to set some common CMake options in the top CMakeLists.txt, like:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fexperimental-library")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi -fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -lc++abi -fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lc++abi -fuse-ld=lld")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
And I want that the example project can be built one time and the sub example can be built independently.
#A.cpp
cmake_minimum_required(VERSION 3.24)
# Something to be added
project(A)
add_executable(${PROJECT_NAME} A.cpp)
But I wish that I can do it without copy the common options into each CMakeLists.txt. I don't find a simple answer on StackOverflow or throughout Google. I think it should be a question may be met frequently in the fact. It's helpful to provide a tutorial even just a tutorial url.
Simply use add_subdirectory? Would simplify things and should still meet your requirement?
option(MYPROJECT_BUILD_EXAMPLES "Build examples" OFF/ON)
...
if (MYPROJECT_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

How can I use Catch2 to test my CMake static library project?

I'm writing a static library which contains some shared code between several projects. In order to verify that the code in this library functions properly I'd like to use Catch2 to do some unit testing on it.
Unfortunately, when attempting to run the tests I run into the problem that the compilation's output file is a shared library (.a), rather than an executable.
I'm sure I can create a separate project which uses the functions from my static library, and subsequently run tests that way, but ideally I'd like to keep the tests and build configurations as close as possible to one another.
So my question is:
what's the best way to set up my project such that I can use Catch2 for unit testing my static library code?
Here's my project's CMakeLists.txt file for reference:
project(sharedLib CXX)
find_package(OpenMP)
if (CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -lpthread -Wall -Wextra -Wpedantic -std=c++17")
endif()
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fopenmp /W4 /std:c++latest")
endif()
include_directories (
src/
lib/Catch2/single_include/
)
file (GLOB_RECURSE LIBRARY_SOURCES src/*.cpp
src/*.c
tests/*.cpp)
add_library(${PROJECT_NAME} STATIC ${LIBRARY_SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC src/)
A common pattern for testing static libraries is to have a separate executable which contains all the tests, and then consumes your library. for example
file (GLOB_RECURSE TEST_SOURCES tests/*.cpp)
add_executable(my_lib_tests test_main.cpp ${TEST_SOURCES})
target_link_libraries(my_lib_tests PRIVATE sharedLib)
target_include_directories(my_lib_tests PRIVATE ../path/to/secret/impl/details)
Here I also have added some include some directories to implementation details of your shared lib which you may need to test, but don't want to expose to clients via a public header.
test_main.cpp need only be:
#define CONFIG_CATCH_MAIN
#include <catch2/catch.hpp>
Then you don't have to include things in your library's build that are unrelated to the library itself, speeding up compilation time for clients, while you can work from the perspective of the test fixture

CMakeLists C program with gtest(C++)

I want to create a CMakeLists that outputs two versions of my executable. One is going to be a release version of my C app.
The other is the gtest version of my app.
cmake_minimum_required(VERSION 3.1)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "C:\\Users\\James\\ClionProjects\\DustAgent\\build")
project(DustAgent)
include_directories ( WindowsApi gtest-1.7.0/include )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=c99 -pthread")
set(SOURCE_FILES main.c utilities/utilities.c utf8/utf8.c)
set(GTEST_SOURCE_FILES ${SOURCE_FILES} gtest-1.7.0/src/gtest-all.cc)
add_executable(DustAgent ${SOURCE_FILES})
How do I make it so that the first exe doesn't require the google library and how do I give specific gcc options for c++ to the gtest version?
you should create a library first and then link both, the executable and the test, with it. The executable and the test should have a separate source code though.
add_library(DustAgentLibrary utilities/utilities.c utf8/utf8.c)
add_executable(DustAgent main.c)
target_link_libraries(DustAgent DustAgentLibrary)
add_executable(DustAgentTest test.c)
target_link_libraries(DustAgentTest DustAgentLibrary gtest)
add_test(DustAgentTest DustAgentTest)

Unable to link an executable to shared library

I have a cmake project where I am trying to link the executable to the shared library. But it is not getting linked. After searching enough and not finding any useful solutions, I'm posting my question here, please let me know if there are any obvious mistakes as I am not familiar with cmake
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
# Set Project Name
set(PROJECT_NAME myproj)
project(${PROJECT_NAME})
# Tell Cmake to invoke gcc with specific flags. Use c++11 standard.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# Include all headers
include_directories(${PROJECT_SOURCE_DIR}/../public/include)
# Driver Program
file(GLOB_RECURSE SOURCE_FILES
"${PROJECT_SOURCE_DIR}/src/*.cpp"
)
# Dont know what to do about this
#set( CMAKE_SKIP_BUILD_RPATH true)
link_directories(${CMAKE_SOURCE_DIR}/../relative/path/to/sharedlib) #contains libshared.so
# Generate Executable, trying to generate shared library to see if it generates # correct dependencies
# add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
#Link the libraries
target_link_libraries(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/../relative/path/to/sharedlib/libshared.so)
Here is the steps I have tried and some observations.
If I generate a shared library instead of an executable, it is able to find the dependent shared library(i.e libshared.so)
ldd myproj.so
libshared.so => full/path/to/sharedlib/libshared.so (0x00007fa26c263000)
I did not fully understand what it meant, but it is able to find the shared library is what I guessed.
If I try to generate an executable instead of shared library, I see undefined reference errors to the functions within the library.
I tried just target_link_libraries(${PROJECT_NAME} shared) as well and it gave same error.
Any clues as to how can I get the shared library linked to my executable? Thanks