Hello every one. I’m a beginner in cmake. I try to rebuild a project that i did on QT with qmake but this time with cmake but i have a lot of difficulties to make it work. all libraries in subdirectory return an error ln2019 and i don’t know why.
as i did more or less the same things for all libraries, I will try to be more precise with one of them and correct the others according to your help.
Here the structure of the code for the fit library:
CMakeLists.txt
AstroBase
├── src
. ├── CMakeLists.txt
. ├── main.cpp
. ├── mainwindow.h
. ├── mainwindow.cpp
. ├── mainwindow.ui
. ├──utils
. . ├── CMakeLists.txt
. . └── fit
. . . ├── CMakeLists.txt
. . . ├── fit.h
. . . └── fit.cpp
here root/CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(AstroBase VERSION 0.1 LANGUAGES CXX)
macro(print_all_variables)
message(STATUS "print_all_variables------------------------------------------{")
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
message(STATUS "print_all_variables------------------------------------------}")
endmacro()
function(add_qt6)
#find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets LinguistTools)
link_libraries(Qt${QT_VERSION_MAJOR}::Widgets)
endfunction()
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(FORMS_DIR "${CMAKE_SOURCE_DIR}/AstroBase/forms")
set(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/AstroBase/include")
set(SOURCE_DIR "${CMAKE_SOURCE_DIR}/AstroBase/src")
set(TS_DIR "${CMAKE_SOURCE_DIR}/AstroBase/TS")
set(CFITSIO_INCLUDE_DIR_X86 "C:/vcpkg/vcpkg/packages/cfitsio_x86-windows/include/")
set(CFITSIO_INCLUDE_DIR_X64 "C:/vcpkg/vcpkg/packages/cfitsio_x64-windows/include/")
set(CFITSIO_LIB_DIR_X86 "C:/vcpkg/vcpkg/packages/cfitsio_x86-windows/lib")
set(CFITSIO_LIB_DIR_X64 "C:/vcpkg/vcpkg/packages/cfitsio_x86-windows/lib")
#include("C:/opencv/opencv/sources/cmake/FindOpenCV.cmake")
set(OpenCV_DIR "C:/opencv/opencv/build")
find_package( OpenCV REQUIRED )
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${FORMS_DIR})
include_directories(${INCLUDE_DIR})
include_directories(${SOURCE_DIR})
include_directories(${TS_DIR})
#file(GLOB_RECURSE SOURCES
# "${FORMS_DIR}/*.ui"
# "${FORMS_DIR}/*.qrc"
# "${INCLUDE_DIR}/*.h"
# "${SOURCE_DIR}/*.cpp"
# "${TS_DIR}/*.ts")
set(PROJECT_SOURCES
${SOURCE_DIR}/main.cpp
${SOURCE_DIR}/mainwindow.cpp
${SOURCE_DIR}/mainwindow.h
${SOURCE_DIR}/mainwindow.ui
)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets LinguistTools)
set(TS_FILES "${TS_DIR}/AstroBase_fr_FR.ts")
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(AstroBase
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET AstroBase APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
else()
if(ANDROID)
add_library(AstroBase SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(AstroBase
${PROJECT_SOURCES}
)
endif()
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
endif()
target_link_libraries(AstroBase PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
#add_library(opencv_world470 STATIC IMPORTED)
#set_property(TARGET opencv_world470 PROPERTY IMPORTED_IMPLIB "C:/opencv/opencv/build/x64/vc16/lib/opencv_world470.lib")
#target_link_directories(AstroBase PRIVATE "C:/opencv/opencv/build/x64/vc16/lib")
target_link_libraries(AstroBase PRIVATE ${OpenCV_LIBS})
add_subdirectory("./AstroBase/src")
target_include_directories(AstroBase PRIVATE ${CFITSIO_INCLUDE_DIR_X64})
target_link_directories(AstroBase PRIVATE ${CFITSIO_LIB_DIR_X64})
add_library(cfitsio STATIC ${CFITSIO_INCLUDE_DIR_X64}
${CFITSIO_LIB_DIR_X64})
set_target_properties(AstroBase PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
install(TARGETS AstroBase
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(AstroBase)
endif()
CMakeLists for ./AstroBase/src:
add_executable(automata ${PROJECT_SOURCES})
add_qt6()
add_subdirectory(widgets)
add_subdirectory(utils)
add_subdirectory(data_struct)
target_link_libraries(automata PUBLIC
widgets
utils
dataStruct)
CMakeLists for ./AstroBase/src/utils:
add_library(utils "")
add_subdirectory(fit)
target_link_libraries(utils PRIVATE
fit)
CMakeLists for ./AstroBase/src/utils/fit:
add_library(fit fit.cpp)
target_include_directories(fit PRIVATE ${CFITSIO_INCLUDE_DIR_X64})
target_link_directories(fit PRIVATE ${CFITSIO_LIB_DIR_X64})
#add_library(cfitsio STATIC ${CFITSIO_INCLUDE_DIR_X64}
# ${CFITSIO_LIB_DIR_X64})
target_sources(fit
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/fit.cpp
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/fit.h
)
target_include_directories(fit
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
I know this cmakes can look like little bit dirty but it’s my first cmakes and i tried a lot of things
here the code for fit.cpp
#include "fit.h"
#include <QDebug>
void Fit::open(const char* path , img* Img) {
int status = 0,nkeys;
int nullval = 0;
int anynul = 0;
fitsfile* fptr;
char ctmp[80], comment[120];
fits_open_file(&fptr, path, READONLY, &status); // open file
fits_get_hdrspace(fptr, &nkeys, NULL, &status);
//char** header2 = new char*[nkeys];
Img->header = new arrayS<arrayS<char>>(nkeys);
//Img->header->size = new long[2];
for (int ii = 1; ii <= nkeys; ii++) {
//header2[ii-1] = new char[FLEN_CARD];
Img->header->ary = new arrayS<char>(FLEN_CARD);
fits_read_record(fptr, ii, Img->header->ary->ary, &status);
}
/*Img->header->array = header2;
Img->header->size[0] = nkeys;
Img->header->size[1] = FLEN_CARD;*/
fits_read_key(fptr, TSTRING, "BITPIX", ctmp, comment, &status);
Img->bitEncoding = std::stoi(ctmp);
fits_read_key(fptr, TSTRING, "NAXIS", ctmp, comment, &status);
Img->naxis = std::stoi(ctmp);
qDebug() << Img->bitEncoding << " " << Img->naxis;
fits_get_img_dim(fptr, &Img->dim, &status); // get dim of image (color or gray scale basicly
Img->size = new long[Img->dim];
fits_get_img_size(fptr, 2, Img->size, &status); // get size of image (pixels)
Img->totalPixels = getTotalPixel(Img->dim, Img->size);
Img->data = new unsigned short[Img->totalPixels];
fits_read_img(fptr, USHORT_IMG, 1, Img->totalPixels, &nullval, Img->data, &anynul, &status);
fits_close_file(fptr, &status);
}
void Fit::save(img *Img)
{
fitsfile* fptr;
int status = 0;
unsigned short **data = (unsigned short **)malloc(Img->size[1] * sizeof(unsigned short *));
for (int i=0; i<Img->size[1]; i++) {
data[i] = (unsigned short *)malloc(Img->size[0] * sizeof(unsigned short));
for(int j = 0; j < Img->size[0]; j++)
data[i][j] = Img->data[i * Img->size[1] + j];
}
long size[2] = {Img->size[0], Img->size[1]};
fits_create_file(&fptr, Img->path, &status);
fits_create_img(fptr, SHORT_IMG, Img->naxis, size, &status);
fits_write_img(fptr, TSHORT, 1, Img->totalPixels, Img->data, &status);
qDebug() << "save " << Img->path;
delete data;
}
int Fit::getTotalPixel(int dim, long* size) {
int multOfAllPixel = 1;
for (int i = 0; i < dim; i++)
multOfAllPixel *= size[i];
return multOfAllPixel;
}
and fit.h
#ifndef FIT_H
#define FIT_H
#include "cfitsio/fitsio.h"
#include "../../data_struct/structurs.h"
#include <vector>
#include <utility>
using namespace std;
class Fit
{
public:
static void open(const char* path, img * Img);
static void save(img * Img);
private:
static int getTotalPixel(int dim, long * size);
};
#endif // FIT_H
and also the code of the main.cpp where i did the test:
#include "mainwindow.h"
#include <QApplication>
#include <QLocale>
#include <QTranslator>
#include "./data_struct/structurs.h"
#include "./utils/fit/fit.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
const QStringList uiLanguages = QLocale::system().uiLanguages();
for (const QString &locale : uiLanguages) {
const QString baseName = "AstroBase_" + QLocale(locale).name();
if (translator.load(":/i18n/" + baseName)) {
a.installTranslator(&translator);
break;
}
}
img* test = new img();
string y = "../imtest.fits";
const char* yolo = y.c_str();
Fit::open(yolo, test);
MainWindow w;
w.show();
return a.exec();
}
the error that i get is this one:
LNK2019 unresolved external symbol "public: static void __cdecl Fit::open(char const *,struct img *)" (?open@Fit@@SAXPEBDPEAUimg@@@Z) refer in function main
can you explain me what i do wrong in my cmakes pls? that quit a long time that im fighting with this (and others problems that i solved already).
Thank you in advance.