admin管理员组文章数量:1279237
I've successfully completed creating a static library in CMake, however I'm completely lost about translating to a template class or to generic programming example. To my understanding, template builds that are purely in .hpp/inl files are all you need.
Do I have a CMake issue? How would the CMakeLists.txt look like? Any explanations or comments in the code would be super helpful. The attempts I tried didn't create a static library and couldn't link the library to the executable. Building it on Windows.
// ========= example code =========
functions.hpp
template <class t>
class Functions
{
public:
Functions() = default;
static t add(t num1, t num2);
static t subtract(t num1, t num2);
static t multiply(t num1, t num2);
static t divide(t num1, t num2);
};
#include "functions.inl"
functions.inl
template<class t>
inline t Functions<t>::add(t num1, t num2) {
return num1 + num2;
}
template<class t>
inline t Functions<t>::subtract(t num1, t num2) {
return num1 - num2;
}
template<class t>
inline t Functions<t>::multiply(t num1, t num2) {
return num1 * num2;
}
template<class t>
inline t Functions<t>::divide(t num1, t num2) {
return num1 / num2;
}
main.cpp
#include <cstdlib>
#include <iostream>
#include "functions.hpp"
int main() {
Functions<double> functions;
// testing all the static library functions
auto sum = functions.add(4.2, 8.33);
auto subtract = functions.subtract(5.32, 9.31);
auto multiply = functions.multiply(3.33, 1.5);
auto divide = functions.divide(5.9, 2.1);
std::cout << "sum: " << sum << std::endl;
std::cout << "subtract: " << subtract << std::endl;
std::cout << "multiply: " << multiply << std::endl;
std::cout << "divide: " << divide << std::endl;
return EXIT_SUCCESS;
}
CMakeLists.txt
# required for any cmake project
cmake_minimum_required(VERSION 3.31 FATAL_ERROR)
# names project and language
project(staticLibs LANGUAGES CXX)
# generates static library from source
add_library(functions
STATIC # keyword determines what type of lib
functions.hpp
functions.inl
)
# create an executable using the static lib
add_executable(main main.cpp)
# need to link the static lib target called 'functions' to the executable
# or executable won't know what library's functions to use
target_link_libraries(main functions)
# makes sure the compiler knows that c++ is used for the static lib
set_target_properties(functions PROPERTIES LINKER_LANGUAGE CXX)
build commands (for debug)
cmake -S . -B build
cmake --build build
---- error(s) ----
Linker issue occurred for me, because static library wasn't created inside my "build" directory.
LINK : fatal error LNK1104: cannot open file 'Debug\functions.lib'
I've successfully completed creating a static library in CMake, however I'm completely lost about translating to a template class or to generic programming example. To my understanding, template builds that are purely in .hpp/inl files are all you need.
Do I have a CMake issue? How would the CMakeLists.txt look like? Any explanations or comments in the code would be super helpful. The attempts I tried didn't create a static library and couldn't link the library to the executable. Building it on Windows.
// ========= example code =========
functions.hpp
template <class t>
class Functions
{
public:
Functions() = default;
static t add(t num1, t num2);
static t subtract(t num1, t num2);
static t multiply(t num1, t num2);
static t divide(t num1, t num2);
};
#include "functions.inl"
functions.inl
template<class t>
inline t Functions<t>::add(t num1, t num2) {
return num1 + num2;
}
template<class t>
inline t Functions<t>::subtract(t num1, t num2) {
return num1 - num2;
}
template<class t>
inline t Functions<t>::multiply(t num1, t num2) {
return num1 * num2;
}
template<class t>
inline t Functions<t>::divide(t num1, t num2) {
return num1 / num2;
}
main.cpp
#include <cstdlib>
#include <iostream>
#include "functions.hpp"
int main() {
Functions<double> functions;
// testing all the static library functions
auto sum = functions.add(4.2, 8.33);
auto subtract = functions.subtract(5.32, 9.31);
auto multiply = functions.multiply(3.33, 1.5);
auto divide = functions.divide(5.9, 2.1);
std::cout << "sum: " << sum << std::endl;
std::cout << "subtract: " << subtract << std::endl;
std::cout << "multiply: " << multiply << std::endl;
std::cout << "divide: " << divide << std::endl;
return EXIT_SUCCESS;
}
CMakeLists.txt
# required for any cmake project
cmake_minimum_required(VERSION 3.31 FATAL_ERROR)
# names project and language
project(staticLibs LANGUAGES CXX)
# generates static library from source
add_library(functions
STATIC # keyword determines what type of lib
functions.hpp
functions.inl
)
# create an executable using the static lib
add_executable(main main.cpp)
# need to link the static lib target called 'functions' to the executable
# or executable won't know what library's functions to use
target_link_libraries(main functions)
# makes sure the compiler knows that c++ is used for the static lib
set_target_properties(functions PROPERTIES LINKER_LANGUAGE CXX)
build commands (for debug)
cmake -S . -B build
cmake --build build
---- error(s) ----
Linker issue occurred for me, because static library wasn't created inside my "build" directory.
LINK : fatal error LNK1104: cannot open file 'Debug\functions.lib'
Share
Improve this question
edited yesterday
Kynosis
asked Feb 24 at 22:20
KynosisKynosis
291 silver badge5 bronze badges
6
|
Show 1 more comment
2 Answers
Reset to default 2At a guess the issue is that you don't actually create a library because there is no code to put in the library.
You probably need at least one non-template function or class to actually create a library.
What you actually created was a header that your project can consume without needing to link in a library.
Templates are a bit weird in that then will get embedded in the compilation unit that uses them rather than separately where they are defined. (There is a lot of long history and good reasons for it, but it makes them a bit of a pain to use as you are discovering). You can read a little more in this discussion
As a side note: I personally prefer to just put the full implementation of a template in the class declaration rather than separate the declaration and definition. I think the result is cleaner and honestly separating the declaration and definition in general results in a lot of code duplication and arcane syntax and is mostly important to keep compilation times reasonable. But I am probably in the minority with that opinion.
Anyway, if you don't have anything else to put in the library, just include your template header directly from main and call it good.
Templates have no effect until you actually instantiate them. There is nothing to put in your static library until you actually instantiate your Function template class with some type. For example, you could add a file functions_double.cpp
that includes your functions.hpp
and then just simply instantiates Functions<double>
:
#include "functions.hpp"
template class Functions<double>;
Add that file into your CMake add_library()
instead of the header files:
# generates static library from source
add_library(functions
STATIC # keyword determines what type of lib
functions_double.cpp
)
You should have your static library built now.
You might also wish to carefully think if you really need and want to pre-instantiate your Functions, or if, instead of static library and header files, you think of your functions.hpp as a header-only library.
P.S. In classic C++, for improved build robustness, you better have include guards in your header file so that it will only be included once and not try to redefine and fail your build if this header file is included multiple times (by another include file requiring it).
本文标签: Creating a StaticShared Library with Header Only C Templates using CMakeStack Overflow
版权声明:本文标题:Creating a StaticShared Library with Header Only C++ Templates using CMake - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741238873a2363569.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
inline
keyword for the templates, as they are not real functions but only something to create functions from. The compiler will handle not creating multiple copies of the same instance. – BoP Commented Feb 24 at 22:59inline
keyword to really small function definitions -- like one liners -- helps speed up your code because it prevents the function call and just pastes your code directly into the executable? So is this only true with non-templated functions then? – Kynosis Commented Feb 25 at 17:37functions
wasn't created mysteriously, so I think that's why the compilers is saying there's a linker error. The CMake commands can't link something to the executable if it doesn't exist. No errors before that. – Kynosis Commented Feb 25 at 17:46inline
has very little to do with inlining nowadays, the compilers are smart enough to figure that out anyway. You have to use it for functions defined in headers, to avoid duplicates when included in multiple cpp files. It is not really an optimization hint. And, like my previous comment said, a template is really not a function, just ... eh ... a template to build a function. – BoP Commented Feb 25 at 19:12