Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake install is broken #3269

Closed
alexreinking opened this issue Jan 30, 2021 · 20 comments · Fixed by #3270
Closed

CMake install is broken #3269

alexreinking opened this issue Jan 30, 2021 · 20 comments · Fixed by #3270

Comments

@alexreinking
Copy link

alexreinking commented Jan 30, 2021

Environment

  • Tesseract Version: master branch (cloned today)
  • Commit Number: c6539e2
  • Platform: Linux hostname 5.4.72-microsoft-standard-WSL2 #1 SMP Wed Oct 28 23:40:43 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Current Behavior:

I run the following commands to build Tesseract and install it into a local directory:

$ git clone [email protected]:tesseract-ocr/tesseract.git
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S tesseract -B tesseract-build
$ cmake --build tesseract-build
$ cmake --install tesseract-build --prefix tesseract-install

Then I create the following CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project(test)
find_package(Tesseract 5 REQUIRED)

in the directory test. I then try to build it:

$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$(readlink -f tesseract-install) -DLeptonica_DIR=$(readlink -f leptonica-install/lib/cmake) -S test -B test-build
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.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 Error at /path/to/tesseract-install/lib/cmake/tesseract/TesseractConfig.cmake:33 (message):
  File or directory
  /path/to/tesseract-install/include;/path/to/tesseract-install/include/tesseract
  referenced by variable Tesseract_INCLUDE_DIRS does not exist !
Call Stack (most recent call first):
  /path/to/tesseract-install/lib/cmake/tesseract/TesseractConfig.cmake:49 (set_and_check)
  CMakeLists.txt:4 (find_package)

Looking in /path/to/tesseract-install/lib/cmake/tesseract/TesseractConfig.cmake, I see:

set_and_check(Tesseract_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include;${PACKAGE_PREFIX_DIR}/include/tesseract")

Which is obviously wrong (contains a ;).

Expected Behavior:

For find_package to succeed.

Suggested Fix:

Do not use CMakePackageConfigHelpers's set_and_check macro. It only works with one path, not several. Here, INCLUDE_DIR is set to a list of two directories:

set(INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" "${CMAKE_INSTALL_PREFIX}/include/tesseract")

Here it is passed to configure_package_config_file. The option NO_SET_AND_CHECK_MACRO should be given here.

tesseract/CMakeLists.txt

Lines 372 to 376 in c6539e2

configure_package_config_file(
cmake/templates/TesseractConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake/tesseract/TesseractConfig.cmake
INSTALL_DESTINATION lib/cmake/tesseract
PATH_VARS INCLUDE_DIR)

And here it is passed to set_and_check. This should just be replaced with normal set or custom checking logic should be implemented.

set_and_check(Tesseract_INCLUDE_DIRS "@PACKAGE_INCLUDE_DIR@")

@Shreeshrii
Copy link
Collaborator

Shreeshrii commented Jan 30, 2021 via email

@alexreinking
Copy link
Author

See https://github.com/tesseract-ocr/tesseract/actions/runs/522034896/workflow for cmake builds which work.

Those builds do not attempt to find_package tesseract. They test the command line tool out of an installation directory (which is not created in a way materially different than how I have done it).

@alexreinking
Copy link
Author

alexreinking commented Jan 30, 2021

I updated my original post with the exact problem spelled out in full detail. This problem was introduced recently, in #3119. I suggest you add some basic CMake package testing to GHA. Even something as simple as checking that find_package succeeds would be very valuable and take next to no time on CI.

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

I think we just need to use simple set instead (as in example). Can you confirm if this approach is works for you?

@alexreinking
Copy link
Author

alexreinking commented Jan 30, 2021

I think we just need to use simple set instead (as in example). Can you confirm if this approach is works for you?

Sort of -- find_package now succeeds, but I get a linker error:

$ cmake --build test-build/
[2/2] Linking CXX executable main
FAILED: main
: && /usr/bin/c++ -O3 -DNDEBUG  CMakeFiles/main.dir/main.cpp.o -o main  /path/to/tesseract-install/lib/libtesseract.a  -lpthread  -llept  /usr/lib/x86_64-linux-gnu/libarchive.so && :
/usr/bin/ld: CMakeFiles/main.dir/main.cpp.o: in function `main':
main.cpp:(.text.startup+0x52): undefined reference to `tesseract::TessBaseAPI::Init(char const*, char const*, tesseract::OcrEngineMode, char**, int, GenericVector<STRING> const*, GenericVector<STRING> const*, bool)'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

Could you provide used CMakeLists.txt (for example project)?

@alexreinking
Copy link
Author

alexreinking commented Jan 30, 2021

Could you provide used CMakeLists.txt (for example project)?

Yes, it's this:

cmake_minimum_required(VERSION 3.19)
project(test)

find_package(Tesseract 5 REQUIRED)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE Tesseract::libtesseract)

The file main.cpp is just the first example from here (I am not a regular tesseract user, I'm helping a colleague who is with their build): https://github.com/tesseract-ocr/tessdoc/blob/master/APIExample.md#basic-example

#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>

int main()
{
    char *outText;

    tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
    // Initialize tesseract-ocr with English, without specifying tessdata path
    if (api->Init(NULL, "eng")) {
        fprintf(stderr, "Could not initialize tesseract.\n");
        exit(1);
    }

    // Open input image with leptonica library
    Pix *image = pixRead("/usr/src/tesseract/testing/phototest.tif");
    api->SetImage(image);
    // Get OCR result
    outText = api->GetUTF8Text();
    printf("OCR output:\n%s", outText);

    // Destroy used object and release memory
    api->End();
    delete api;
    delete [] outText;
    pixDestroy(&image);

    return 0;
}

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

Thanks! Could you also provide the generated Tesseract cmake config file (from install prefix)?

@alexreinking
Copy link
Author

alexreinking commented Jan 30, 2021

Here are the contents of the lib/cmake/tesseract folder: TesseractCMake.zip

And here is the verbose build output so you can see the actual commands (with local paths again redacted):

$ ls app
CMakeLists.txt  main.cpp
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$(readlink -f tesseract-install) -S app -B app-build
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.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
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/app-build
$ cmake --build app-build/ -- -v
[1/2] /usr/bin/c++   -O3 -DNDEBUG -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /path/to/app/main.cpp
[2/2] : && /usr/bin/c++ -O3 -DNDEBUG  CMakeFiles/main.dir/main.cpp.o -o main  /path/to/tesseract-install/lib/libtesseract.a  -lpthread  -llept  /usr/lib/x86_64-linux-gnu/libarchive.so && :
FAILED: main
: && /usr/bin/c++ -O3 -DNDEBUG  CMakeFiles/main.dir/main.cpp.o -o main  /path/to/tesseract-install/lib/libtesseract.a  -lpthread  -llept  /usr/lib/x86_64-linux-gnu/libarchive.so && :
/usr/bin/ld: CMakeFiles/main.dir/main.cpp.o: in function `main':
main.cpp:(.text.startup+0x52): undefined reference to `tesseract::TessBaseAPI::Init(char const*, char const*, tesseract::OcrEngineMode, char**, int, GenericVector<STRING> const*, GenericVector<STRING> const*, bool)'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

@alexreinking, thanks, can reproduce. Did this work before my PR?

@alexreinking
Copy link
Author

@alexreinking, thanks, can reproduce. Did this work before my PR?

I do not know, but I will try. Give me a couple minutes.

@alexreinking
Copy link
Author

@alexreinking, thanks, can reproduce. Did this work before my PR?

No because the install is broken in too many other ways. Can't find TesseractTargets.cmake, the config files aren't in a standard path, etc.

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

Could you try to specify Tesseract_ROOT path to the .cmake files location?

@alexreinking
Copy link
Author

alexreinking commented Jan 30, 2021

Could you try to specify Tesseract_ROOT path to the .cmake files location?

You mean in addition to Tesseract_DIR? That's how I got the error regarding the targets file and gave up.

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

No, only the Tesseract_ROOT that points to the .cmake files location.

@alexreinking
Copy link
Author

alexreinking commented Jan 30, 2021

No, only the Tesseract_ROOT that points to the .cmake files location.

I was not able to make it work with the commit prior to #3119

@Shatur
Copy link
Contributor

Shatur commented Jan 30, 2021

Do you mean that you are getting a link error or that it didn't work at all prior to #3119?

@Shatur
Copy link
Contributor

Shatur commented Jan 31, 2021

I think that there is another link issue that not caused by my changes. @alexreinking could you open a separate issue about it?

@Shreeshrii
Copy link
Collaborator

@Shatur
Copy link
Contributor

Shatur commented Feb 18, 2021

Related post: https://stackoverflow.com/questions/65970070/use-tesseract-in-cmake-project

I wrote find modules for Tesseract and Leptonica (find modules are needed because other distributions usually use Autotools to build these projects):

https://github.com/crow-translate/crow-translate/blob/master/cmake/FindTesseract.cmake
https://github.com/crow-translate/crow-translate/blob/master/cmake/FindLeptonica.cmake

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants