find_package( ... NO_MODULE ) not working properly

For FLTK. If I set FLTK_DIR to a build directory in the CMakeLists.txt file and then run find_package( FLTK REQUIRED NO_MODULE ), I get an error message:

CMake Error at mrViewer/src/CMakeLists.txt:53 (FIND_PACKAGE):
Could not find a package configuration file provided by “FLTK” with any of
the following names:

FLTKConfig.cmake
fltk-config.cmake

Add the installation prefix of “FLTK” to CMAKE_PREFIX_PATH or set
“FLTK_DIR” to a directory containing one of the above files. If “FLTK”
provides a separate development package or SDK, be sure it has been
installed.

If I set FLTK_DIR in the command-line all works fine. I already checked the cache and it is not that.

FLTK_DIR's build directory may not contain a config file, so that wouldn’t necessarily work. The named files need to exist for _DIR variables to work with find_package(NO_MODULE).

FLTK_DIR contains a FLTKConfig.cmake file. However cmake does not find it.

As I said, if I set FLTK_DIR from the command-line with -DFLTK_DIR=path/to/fltk/build it all works well.

Could you use cmake --debug-find to get the information related to searching for FLTK?

I got the information and my build directory is not listed. Most directories seem part of $PATH.

/home/gga/.rbenv/FLTKConfig.cmake
/home/gga/.rbenv/fltk-config.cmake
/home/gga/code/applications/mrv/BUILD/Linux-4.4.0-148-generic-64/Release/tmp/FLTKConfig.cmake
/home/gga/code/applications/mrv/BUILD/Linux-4.4.0-148-generic-64/Release/tmp/fltk-config.cmake
/home/gga/FLTKConfig.cmake
/home/gga/fltk-config.cmake
/usr/local/heroku/FLTKConfig.cmake
/usr/local/heroku/fltk-config.cmake
/home/gga/.cargo/FLTKConfig.cmake
/home/gga/.cargo/fltk-config.cmake
/usr/local/FLTKConfig.cmake
/usr/local/fltk-config.cmake
/usr/local/cmake/FLTKConfig.cmake
/usr/local/cmake/fltk-config.cmake
/usr/FLTKConfig.cmake
/usr/fltk-config.cmake
/FLTKConfig.cmake
/fltk-config.cmake
/usr/games/FLTKConfig.cmake
/usr/games/fltk-config.cmake
/usr/local/games/FLTKConfig.cmake
/usr/local/games/fltk-config.cmake
/home/gga/.local/FLTKConfig.cmake
/home/gga/.local/fltk-config.cmake
/opt/FLTKConfig.cmake
/opt/fltk-config.cmake

The build directory should be ~/code/lib/fltk-x11/build-linux.

Once I run it with -DFLTK_DIR, the directory is found as the first and only path.

That makes sense. If a _DIR variable is not useful, its value is cleared (historical behavior; it’s annoying), so there is probably some second-configure issues popping up here.

Second-configure issues. Like what? What should I look for?

I mean issues that arise because of cache differences that make a project do different things with cmake . versus cmake . && cmake . (which CI usually skips, so it is only developers that see it).

You say that it is now found with FLTK_DIR, so is this resolved?

No. It finds FLTK_DIR only if I pass it command-line (and run it afterwards, too). However, what I really wanted was to set the FLTK_DIR path in the CMakeLists.txt file and that does not work. I really never wanted to pass the path command-line. I wanted to hard-code it in the CMakeLists.txt file.

Did you already tried to make FLTK_DIR a cache variable, i.e. set(FLTK_DIR "path/to/fltk/build" CACHE FILEPATH "Package config directory of FLTK")? One difference between a CMake command line argument and a plain set command (without CACHE keyword) is that the former creates a CACHE entry while the latter does not. And the cached variable is shadowing the normal variable.

Yes. I tried setting FLTK_DIR as a CACHE variable to no effect.

Can you please share the code that doesn’t work in the CMake code?


cmake_minimum_required (VERSION 3.2.3)

project (flruler)

## Find FLTK
## Note: FLTK_DIR *MUST* be defined on the commandline or in the CMake GUI, e.g.
## cmake -G Ninja -DFLTK_DIR="/path/to/fltk/build" ..

set (FLTK_DIR "/home/gga/lib/fltk-x11/build-linux" CACHE FILEPATH "FLTK installation or build directory")
find_package (FLTK REQUIRED NO_MODULE)

# debugging: if (1) = yes, if (0) = no

if (1)
  message (STATUS "--- Project: ${CMAKE_PROJECT_NAME} ---")
  message (STATUS "FLTK_VERSION          = '${FLTK_VERSION}'")
  message (STATUS "FLTK_INCLUDE_DIRS     = '${FLTK_INCLUDE_DIRS}'")
  message (STATUS "FLTK_INCLUDE_DIR      = '${FLTK_INCLUDE_DIR}'")
  message (STATUS "FLTK_LIBRARIES        = '${FLTK_LIBRARIES}'")
  message (STATUS "FLTK_FLUID_EXECUTABLE = '${FLTK_FLUID_EXECUTABLE}'")
  message (STATUS "FLTK_USE_FILE         = '${FLTK_USE_FILE}'")
endif ()


# overwrite FLTK_LIBRARIES which is empty in current FLTKConfig.cmake
# add all required libraries like "fltk_images fltk_gl fltk"
# this project needs only "fltk"

set (FLTK_LIBRARIES fltk)


message (STATUS "FLTK_LIBRARIES        = '${FLTK_LIBRARIES}'")

# Build flruler executable

set (SOURCES flruler.C)
add_executable (flruler WIN32 MACOSX_BUNDLE ${SOURCES})
target_include_directories (flruler PRIVATE ${FLTK_INCLUDE_DIRS})
target_link_libraries (flruler ${FLTK_LIBRARIES})

type or paste code here

//
// flruler -- draw an onscreen ruler for GUI design measurements
//
//   Version 1.05
//   Copyright (C) 2006,2020 Greg Ercolano
//
//   This program is free software; you can redistribute it and/or
//   modify it under the terms of the GNU General Public License as
//   published by the Free Software Foundation; either version 2 of
//   the License, or (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//   02111-1307 USA
//
//   To report bugs, create an 'issue' on the project's github page:
//   https://github.com/erco77/flruler
//

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <stdlib.h>	// exit
#include <stdio.h>	// sprintf

#if !defined(__APPLE__) && !defined(_WIN32)
#include <unistd.h>	// fork
#endif

#include "flruler.H"

#ifdef __APPLE__
// OSX
#define XSIZE 100		// XXX: 100px min window size OSX w/fltk 1.1.7
#define YSIZE 53
#define FONTSIZE 9		// 8 too small on osx
#else
// NON-OSX
#define XSIZE 67
#define YSIZE 53
#define FONTSIZE 8		// nice on linux
#endif

// Ruler widget
class RulerWindow : public Fl_Double_Window {
    int horizontal, reverse;
    int xsize, ysize;
    // DRAW A LINE AT X/Y
    //    Obeys 'reverse'
    //
    void Line(int X1,int Y1,int X2,int Y2) {
        if ( reverse ) {
	    X1 = w() - X1 - 1;
	    X2 = w() - X2 - 1;
	    Y1 = h() - Y1 - 1;
	    Y2 = h() - Y2 - 1;
	}
	fl_line(X1,Y1,X2,Y2);
    }
    // DRAW TEXT CENTERED AT X/Y
    //    Obeys 'reverse'
    //
    void TextCenter(const char *s,int X,int Y) {
        if ( reverse && horizontal ) {
	    X = w()-X-1;
	} else if ( reverse && ! horizontal ) {
	    Y = h()-Y-1;
	}
	// CENTER TEXT
	X = X - ((int)fl_width(s) / 2);
	Y = Y + ((int)fl_height() / 2) - 1;
	fl_draw(s,X,Y);
    }
    // FLTK: DRAW THE SCREEN
    void draw() {
        int RIGHT = w()-1;
	int BOTTOM = h()-1;
        char s[80];
        fl_color(133);		// ORANGE, 132, 92
        fl_rectf(0,0,w(),h());
        fl_color(FL_BLACK);
	fl_font(FL_HELVETICA, FONTSIZE);
	if ( horizontal ) {
	    // Draw horizontal ruler markings
	    for ( int X=0; X<=w(); X+=2 ) {
	        if ( X % 10 == 0 ) {
		    if ( X % 50 == 0 ) {
			Line(X,0,X,20);
			Line(X,BOTTOM-20,X,BOTTOM);
		    } else {
			Line(X,0,X,10);
			Line(X,BOTTOM-10,X,BOTTOM);
			sprintf(s,"%d",(X % 100) / 10);
			TextCenter(s,X,15);
			TextCenter(s,X,BOTTOM-15-1);
		    }
		} else {
	            Line(X,0,X,5);
		    Line(X,BOTTOM-5,X,BOTTOM);
		}
		if ( X % 50 == 0 ) {
		    sprintf(s,"%d",X);
		    TextCenter(s,X,BOTTOM/2);
		}
	    }
	} else {
	    // Draw vertical ruler markings
	    for ( int Y=0; Y<=h(); Y+=2 ) {
	        if ( Y % 10 == 0 ) {
		    if ( Y % 50 == 0 ) {
			Line(0,Y,20,Y);
			Line(RIGHT-20,Y,RIGHT,Y);
		    } else {
			Line(0,Y,10,Y);
			Line(RIGHT-10,Y,BOTTOM,Y);
			sprintf(s,"%d",(Y % 100) / 10);
			TextCenter(s,15,Y);
			TextCenter(s,RIGHT-15-1,Y);
		    }
		} else {
	            Line(0,Y,5,Y);
		    Line(RIGHT-5,Y,RIGHT,Y);
		}
		if ( Y % 50 == 0 ) {
		    sprintf(s,"%d",Y);
		    TextCenter(s,RIGHT/2,Y);
		}
	    }
	}
    }
    // FLTK: EVENT HANDLER
    int handle(int e);

public:
    // CHANGE HORIZONTAL ORIENTATION
    //     val: 1=horiz, 0=vertical
    //     rx: recommended x position for new orientation
    //     ry: recommended y position for new orientation
    //
    void Horizontal(int val, int rx=-1, int ry=-1) {
        horizontal = val;
	if ( horizontal ) {
	    if ( rx == -1 ) rx = 0;
	    if ( ry == -1 ) ry = Fl::event_y_root();
	    resize(rx, ry, xsize, YSIZE);
	} else {
	    if ( rx == -1 ) rx = Fl::event_x_root();
	    if ( ry == -1 ) ry = 0;
	    resize(rx, ry, XSIZE, ysize);
	}
	redraw();
    }
    // CHANGE FORWARD/REVERSE ORIENTATION
    void Reverse(int val) {
        reverse = val;
	redraw();
    }
    // CTOR
    RulerWindow(int W,int H,int hval,int rval):Fl_Double_Window(W,H,0) {
	end();
	resizable(this);
	border(0);
	show();
	xsize = Fl::w();
	ysize = Fl::h();
        Horizontal(hval);
	Reverse(rval);
    }
    // CTOR
    RulerWindow(int X,int Y,int W,int H,int hval, int rval):Fl_Double_Window(X,Y,W,H,0) {
	end();
	resizable(this);
	border(0);
	show();
	xsize = Fl::w();
	ysize = Fl::h();
        Horizontal(hval);
	Reverse(rval);
    }
};

// FLTK: EVENT HANDLER
int RulerWindow::handle(int e) {
    static int xoff = 0, yoff = 0, drag = 0;
    int ret = Fl_Double_Window::handle(e);
    switch ( e ) {
	case FL_KEYBOARD:
	case FL_PUSH:
	    drag = 0;
	    switch ( Fl::event_key() ) {
		// PREPARE FOR WINDOW DRAG
	        case FL_Button+FL_LEFT_MOUSE:
		    switch ( Fl::event_clicks() ) {
		        case 1:		// invert dir
		        case 3:
			    Reverse(reverse ^ 1);
			    break;
		        case 2:		// invert horiz/vert
			    Horizontal(horizontal ^ 1);
			    Reverse(0);
			    break;
		        case 4:
			    Horizontal(horizontal ^ 1);
			    Reverse(1);
			    break;
		    }
		    xoff = x() - Fl::event_x_root();
		    yoff = y() - Fl::event_y_root();
		    drag = 1;
		    break;

		// COPY RULER
	        case FL_Button+FL_MIDDLE_MOUSE:
		case 'c':
		case 'C':
		    new RulerWindow(Fl::event_x_root(),Fl::event_y_root(),0,0,horizontal,reverse);
		    return(1);
		// PUT ZERO AT LEFT
		case FL_Left:
		    Horizontal(1);
		    Reverse(0);
		    return(1);
		// PUT ZERO AT RIGHT
		case FL_Right:
		    Horizontal(1);
		    Reverse(1);
		    return(1);
		// PUT ZERO AT TOP
		case FL_Up:
		    Horizontal(0);
		    Reverse(0);
		    return(1);
		// PUT ZERO AT BOTTOM
		case FL_Down:
		    Horizontal(0);
		    Reverse(1);
		    return(1);
		// RESIZE ruler window
		case '-':		// shrink
		case 65453:		// numeric keypad's '-' key
		    if (horizontal) {
			xsize = xsize * 9 / 10;
			if (xsize < 150) xsize = 150;
			size(xsize,YSIZE);
		    } else {
			ysize = ysize * 9 / 10;
			if (ysize < 150) ysize = 150;
			size(XSIZE,ysize);
		    }
		    return(1);
		case '+':		// enlarge
		case '=':
		case 65451:		// numeric keypad's '+' key
		    if (horizontal) {
			xsize = xsize * 10 / 9;
			if (xsize > Fl::w()) xsize = Fl::w();
			size(xsize,YSIZE);
		    } else {
			ysize = ysize * 10 / 9;
			if (ysize > Fl::h()) ysize = Fl::h();
			size(XSIZE,ysize);
		    }
		    return(1);
		// QUIT
		case FL_Escape:		// fltk close window
		case FL_CTRL+'x':	// cut
		case FL_CTRL+'w':	// close window
		    hide();
		    return(1);
		// QUIT APPLICATION
		case 'q':
		case FL_CTRL+'q':
		case FL_ALT+'q':
		    exit(1);
	    }
	    ret = 1;
	    break;
	case FL_DRAG:
	    if ( drag ) {
		// LET USER DRAG WINDOW AROUND THE SCREEN
		position(xoff + Fl::event_x_root(), yoff + Fl::event_y_root());
		redraw();
	    }
	    ret = 1;
	    break;
	case FL_RELEASE:
	    ret = 1;
	    drag = 0;
	    break;
    }
    return(ret);
}

// FORK APP OFF AS CHILD PROCESS
//    Doesn't work in OSX or WIN32
void Fork() {
#if !defined(__APPLE__) && !defined(_WIN32)
    if ( fork() > 0 ) exit(0);
#endif
}

/// MAIN
int main(int argc, char *argv[]) {
    for ( int t=1; t<argc; t++ ) {
        if ( argv[t][0] == '-' ) {
	    switch ( argv[t][1] ) {
	        case 'h':
		    fprintf(stderr, "%s", G_help);
		    exit(1);
	    }
	}
    }
    Fork();
    int w = Fl::w();
    int h = YSIZE;
    RulerWindow win(w,h,1,0);
    return(Fl::run());
}

// flruler.H

#define VERSION "1.05"

// HELP SCREEN
const char *G_help =
    "\n"
    "flruler - a simple onscreen pixel ruler for debugging GUIs\n"
    "Version " VERSION "\n"
    "\n"
    "KEYBOARD OPERATIONS\n"
    "    'c'                   Make a copy of the current ruler (in focus)\n"
    "    'Esc'                 Closes current ruler (in focus)\n"
    "    'q'                   Quit all rulers\n"
    "    Up,Down,Left,Right    Re-orients ruler (arrow points to where zero will be)\n"
    "\n"
    "MOUSE OPERATIONS\n"
    "    Left-Drag             Drags current ruler around for positioning\n"
    "    Left-Double-click     Reverses direction of current ruler's numbers\n"
    "    Left-Triple-click     Rotates current ruler 90 degrees\n"
    "    Middle-Click          Makes copy of current ruler\n"
    "\n"
    "AUTHOR\n"
    "    Written by Greg Ercolano."
    "\n"
    "    The latest version of flruler can be downloaded from http://seriss.com/people/erco/fltk/flruler/\n"
    "    To build flruler from source, you need FLTK, the multi-platform GPL graphics toolkit\n"
    "    (which supports Windows, Linux, OSX, IRIX..) from http://www.fltk.org/\n"
    "\n"
    "BUGS\n"
    "    To report bugs, create an 'issue' on the project's github page:\n"
    "    https://github.com/erco77/flruler\n"
    "\n"
    "COPYRIGHT\n"
    "    Copyright (C) 2012, 2006 Greg Ercolano.\n"
    "\n"
    "    This is free software; see the source for copying conditions.  There is\n"
    "    NO  warranty;  not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR\n"
    "    PURPOSE. For more information, see the LICENSE file that came with the source.\n";


What happens if you use PATH instead of FILEPATH for the type of the FLTK_DIR variable?

Same thing.